Bullet Collision Detection & Physics Library
btInternalEdgeUtility.cpp
Go to the documentation of this file.
2
5
12
13//#define DEBUG_INTERNAL_EDGE
14
15#ifdef DEBUG_INTERNAL_EDGE
16#include <stdio.h>
17#endif //DEBUG_INTERNAL_EDGE
18
19#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
20static btIDebugDraw* gDebugDrawer = 0;
21
23{
25}
26
27static void btDebugDrawLine(const btVector3& from, const btVector3& to, const btVector3& color)
28{
29 if (gDebugDrawer)
31}
32#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
33
34static int btGetHash(int partId, int triangleIndex)
35{
36 int hash = (partId << (31 - MAX_NUM_PARTS_IN_BITS)) | triangleIndex;
37 return hash;
38}
39
41{
42 const btVector3 refAxis0 = edgeA;
46 return angle;
47}
48
50{
55
57 {
58 //skip self-collisions
60 return;
61
62 //skip duplicates (disabled for now)
63 //if ((m_partIdA <= partId) && (m_triangleIndexA <= triangleIndex))
64 // return;
65
66 //search for shared vertices and edges
67 int numshared = 0;
68 int sharedVertsA[3] = {-1, -1, -1};
69 int sharedVertsB[3] = {-1, -1, -1};
70
72 btScalar crossBSqr = ((triangle[1] - triangle[0]).cross(triangle[2] - triangle[0])).length2();
73 if (crossBSqr < m_triangleInfoMap->m_equalVertexThreshold)
74 return;
75
78 if (crossASqr < m_triangleInfoMap->m_equalVertexThreshold)
79 return;
80
81#if 0
82 printf("triangle A[0] = (%f,%f,%f)\ntriangle A[1] = (%f,%f,%f)\ntriangle A[2] = (%f,%f,%f)\n",
85 m_triangleVerticesA[2].getX(),m_triangleVerticesA[2].getY(),m_triangleVerticesA[2].getZ());
86
87 printf("partId=%d, triangleIndex=%d\n",partId,triangleIndex);
88 printf("triangle B[0] = (%f,%f,%f)\ntriangle B[1] = (%f,%f,%f)\ntriangle B[2] = (%f,%f,%f)\n",
89 triangle[0].getX(),triangle[0].getY(),triangle[0].getZ(),
90 triangle[1].getX(),triangle[1].getY(),triangle[1].getZ(),
91 triangle[2].getX(),triangle[2].getY(),triangle[2].getZ());
92#endif
93
94 for (int i = 0; i < 3; i++)
95 {
96 for (int j = 0; j < 3; j++)
97 {
99 {
102 numshared++;
104 if (numshared >= 3)
105 return;
106 }
107 }
109 if (numshared >= 3)
110 return;
111 }
112 switch (numshared)
113 {
114 case 0:
115 {
116 break;
117 }
118 case 1:
119 {
120 //shared vertex
121 break;
122 }
123 case 2:
124 {
125 //shared edge
126 //we need to make sure the edge is in the order V2V0 and not V0V2 so that the signs are correct
127 if (sharedVertsA[0] == 0 && sharedVertsA[1] == 2)
128 {
129 sharedVertsA[0] = 2;
130 sharedVertsA[1] = 0;
131 int tmp = sharedVertsB[1];
133 sharedVertsB[0] = tmp;
134 }
135
137
139 if (!info)
140 {
143 info = m_triangleInfoMap->find(hash);
144 }
145
146 int sumvertsA = sharedVertsA[0] + sharedVertsA[1];
147 int otherIndexA = 3 - sumvertsA;
148
150
152 int otherIndexB = 3 - (sharedVertsB[0] + sharedVertsB[1]);
153
155 //btTriangleShape tB(triangle[0],triangle[1],triangle[2]);
156
159 tA.calcNormal(normalA);
160 tB.calcNormal(normalB);
161 edge.normalize();
163
164 {
166 if (edgeCrossA.dot(tmp) < 0)
167 {
168 edgeCrossA *= -1;
169 }
170 }
171
173
174 {
176 if (edgeCrossB.dot(tmp) < 0)
177 {
178 edgeCrossB *= -1;
179 }
180 }
181
182 btScalar angle2 = 0;
183 btScalar ang4 = 0.f;
184
187
189 //btVector3 calculatedNormalB = normalA;
190 bool isConvex = false;
191
192 if (len2 < m_triangleInfoMap->m_planarEpsilon)
193 {
194 angle2 = 0.f;
195 ang4 = 0.f;
196 }
197 else
198 {
199 calculatedEdge.normalize();
203 ang4 = SIMD_PI - angle2;
206 isConvex = (dotA < 0.);
207
208 correctedAngle = isConvex ? ang4 : -ang4;
209 }
210
211 //alternatively use
212 //btVector3 calculatedNormalB2 = quatRotate(orn,normalA);
213
214 switch (sumvertsA)
215 {
216 case 1:
217 {
222 if (bla < 0)
223 {
224 computedNormalB *= -1;
226 }
227#ifdef DEBUG_INTERNAL_EDGE
228 if ((computedNormalB - normalB).length() > 0.0001)
229 {
230 printf("warning: normals not identical\n");
231 }
232#endif //DEBUG_INTERNAL_EDGE
233
235
236 if (isConvex)
238 break;
239 }
240 case 2:
241 {
245 if (computedNormalB.dot(normalB) < 0)
246 {
247 computedNormalB *= -1;
249 }
250
251#ifdef DEBUG_INTERNAL_EDGE
252 if ((computedNormalB - normalB).length() > 0.0001)
253 {
254 printf("warning: normals not identical\n");
255 }
256#endif //DEBUG_INTERNAL_EDGE
258 if (isConvex)
260 break;
261 }
262 case 3:
263 {
267 if (computedNormalB.dot(normalB) < 0)
268 {
270 computedNormalB *= -1;
271 }
272#ifdef DEBUG_INTERNAL_EDGE
273 if ((computedNormalB - normalB).length() > 0.0001)
274 {
275 printf("warning: normals not identical\n");
276 }
277#endif //DEBUG_INTERNAL_EDGE
279
280 if (isConvex)
282 break;
283 }
284 }
285
286 break;
287 }
288 default:
289 {
290 // printf("warning: duplicate triangle\n");
291 }
292 }
293 }
294};
295
296
298{
301
302
306 {
307 }
309 {
312 connectivityProcessor.m_triangleIndexA = triangleIndex;
313 connectivityProcessor.m_triangleVerticesA = triangle;
314 connectivityProcessor.m_triangleInfoMap = m_triangleInfoMap;
318 aabbMin.setMin(triangle[0]);
319 aabbMax.setMax(triangle[0]);
320 aabbMin.setMin(triangle[1]);
321 aabbMax.setMax(triangle[1]);
322 aabbMin.setMin(triangle[2]);
323 aabbMax.setMax(triangle[2]);
324
326 }
327};
330
332{
333 //the user pointer shouldn't already be used for other purposes, we intend to store connectivity info there!
334 if (trimeshShape->getTriangleInfoMap())
335 return;
336
337 trimeshShape->setTriangleInfoMap(triangleInfoMap);
338
340 const btVector3& meshScaling = meshInterface->getScaling();
341
342 for (int partId = 0; partId < meshInterface->getNumSubParts(); partId++)
343 {
344 const unsigned char* vertexbase = 0;
345 int numverts = 0;
347 int stride = 0;
348 const unsigned char* indexbase = 0;
349 int indexstride = 0;
350 int numfaces = 0;
351 PHY_ScalarType indicestype = PHY_INTEGER;
352 //PHY_ScalarType indexType=0;
353
355 meshInterface->getLockedReadOnlyVertexIndexBase(&vertexbase, numverts, type, stride, &indexbase, indexstride, numfaces, indicestype, partId);
357
358 for (int triangleIndex = 0; triangleIndex < numfaces; triangleIndex++)
359 {
360 unsigned int* gfxbase = (unsigned int*)(indexbase + triangleIndex * indexstride);
361
362 for (int j = 2; j >= 0; j--)
363 {
364 int graphicsindex;
365 switch (indicestype) {
366 case PHY_INTEGER: graphicsindex = gfxbase[j]; break;
367 case PHY_SHORT: graphicsindex = ((unsigned short*)gfxbase)[j]; break;
368 case PHY_UCHAR: graphicsindex = ((unsigned char*)gfxbase)[j]; break;
369 default: btAssert(0);
370 }
371 if (type == PHY_FLOAT)
372 {
373 float* graphicsbase = (float*)(vertexbase + graphicsindex * stride);
375 graphicsbase[0] * meshScaling.getX(),
376 graphicsbase[1] * meshScaling.getY(),
377 graphicsbase[2] * meshScaling.getZ());
378 }
379 else
380 {
381 double* graphicsbase = (double*)(vertexbase + graphicsindex * stride);
383 }
384 }
387 aabbMin.setMin(triangleVerts[0]);
388 aabbMax.setMax(triangleVerts[0]);
389 aabbMin.setMin(triangleVerts[1]);
390 aabbMax.setMax(triangleVerts[1]);
391 aabbMin.setMin(triangleVerts[2]);
392 aabbMax.setMax(triangleVerts[2]);
393
396 connectivityProcessor.m_triangleIndexA = triangleIndex;
397 connectivityProcessor.m_triangleVerticesA = &triangleVerts[0];
398 connectivityProcessor.m_triangleInfoMap = triangleInfoMap;
399
400 trimeshShape->processAllTriangles(&connectivityProcessor, aabbMin, aabbMax);
401 }
402 }
403}
404
405
407{
408
409 //the user pointer shouldn't already be used for other purposes, we intend to store connectivity info there!
410 if (heightfieldShape->getTriangleInfoMap())
411 return;
412
413 heightfieldShape->setTriangleInfoMap(triangleInfoMap);
414
415 //get all the triangles of the heightfield
416
418
421
423 heightfieldShape->processAllTriangles(&processHeightfield, aabbMin, aabbMax);
424
425}
426
427// Given a point and a line segment (defined by two points), compute the closest point
428// in the line. Cap the point at the endpoints of the line segment.
430{
432
433 // Handle degenerate lines
434 if (lineDelta.fuzzyZero())
435 {
437 }
438 else
439 {
441
442 // Clamp the point to conform to the segment's endpoints
443 if (delta < 0)
444 delta = 0;
445 else if (delta > 1)
446 delta = 1;
447
449 }
450}
451
453{
455 //we only have a local triangle normal, not a local contact normal -> only normal in world space...
456 //either compute the current angle all in local space, or all in world space
457
460
461 if (correctedEdgeAngle < 0)
462 {
464 {
468 return true;
469 }
470 }
471
472 if (correctedEdgeAngle >= 0)
473 {
475 {
479 return true;
480 }
481 }
482 return false;
483}
484
487{
488 //btAssert(colObj0->getCollisionShape()->getShapeType() == TRIANGLE_SHAPE_PROXYTYPE);
489 if (colObj0Wrap->getCollisionShape()->getShapeType() != TRIANGLE_SHAPE_PROXYTYPE)
490 return;
491
492
494
495 if (colObj0Wrap->getCollisionObject()->getCollisionShape()->getShapeType() == TERRAIN_SHAPE_PROXYTYPE)
496 {
497 btHeightfieldTerrainShape* heightfield = (btHeightfieldTerrainShape*)colObj0Wrap->getCollisionObject()->getCollisionShape();
499
500//#define USE_HEIGHTFIELD_TRIANGLES
501#ifdef USE_HEIGHTFIELD_TRIANGLES
502 btVector3 newNormal = btVector3(0, 0, 1);
503
504 const btTriangleShape* tri_shape = static_cast<const btTriangleShape*>(colObj0Wrap->getCollisionShape());
506 tri_shape->calcNormal(tri_normal);
508 // cp.m_distance1 = cp.m_distance1 * newNormal.dot(cp.m_normalWorldOnB);
509 cp.m_normalWorldOnB = newNormal;
510 // Reproject collision point along normal. (what about cp.m_distance1?)
511 cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
512 cp.m_localPointB = colObj0Wrap->getWorldTransform().invXform(cp.m_positionWorldOnB);
513 return;
514#endif
515 }
516
517
519
520 if (colObj0Wrap->getCollisionObject()->getCollisionShape()->getShapeType() == SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE)
521 {
522 trimesh = ((btScaledBvhTriangleMeshShape*)colObj0Wrap->getCollisionObject()->getCollisionShape())->getChildShape();
523 }
524 else
525 {
526 if (colObj0Wrap->getCollisionObject()->getCollisionShape()->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
527 {
528 trimesh = (btBvhTriangleMeshShape*)colObj0Wrap->getCollisionObject()->getCollisionShape();
529 }
530 }
531 if (trimesh)
532 {
534 }
535
536
538 return;
539
540 int hash = btGetHash(partId0, index0);
541
542 btTriangleInfo* info = triangleInfoMapPtr->find(hash);
543 if (!info)
544 return;
545
547
548 const btTriangleShape* tri_shape = static_cast<const btTriangleShape*>(colObj0Wrap->getCollisionShape());
549 btVector3 v0, v1, v2;
550 tri_shape->getVertex(0, v0);
551 tri_shape->getVertex(1, v1);
552 tri_shape->getVertex(2, v2);
553
554 //btVector3 center = (v0+v1+v2)*btScalar(1./3.);
555
556 btVector3 red(1, 0, 0), green(0, 1, 0), blue(0, 0, 1), white(1, 1, 1), black(0, 0, 0);
558 tri_shape->calcNormal(tri_normal);
559
560 //btScalar dot = tri_normal.dot(cp.m_normalWorldOnB);
561 btVector3 nearest;
562 btNearestPointInLineSegment(cp.m_localPointB, v0, v1, nearest);
563
564 btVector3 contact = cp.m_localPointB;
565#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
566 const btTransform& tr = colObj0->getWorldTransform();
567 btDebugDrawLine(tr * nearest, tr * cp.m_localPointB, red);
568#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
569
570 bool isNearEdge = false;
571
572 int numConcaveEdgeHits = 0;
573 int numConvexEdgeHits = 0;
574
575 btVector3 localContactNormalOnB = colObj0Wrap->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB;
576 localContactNormalOnB.normalize(); //is this necessary?
577
578 // Get closest edge
579 int bestedge = -1;
581 //
582 // Edge 0 -> 1
583 if (btFabs(info->m_edgeV0V1Angle) < triangleInfoMapPtr->m_maxEdgeAngleThreshold)
584 {
585 btVector3 nearest;
586 btNearestPointInLineSegment(cp.m_localPointB, v0, v1, nearest);
587 btScalar len = (contact - nearest).length();
588 //
589 if (len < disttobestedge)
590 {
591 bestedge = 0;
592 disttobestedge = len;
593 }
594 }
595 // Edge 1 -> 2
596 if (btFabs(info->m_edgeV1V2Angle) < triangleInfoMapPtr->m_maxEdgeAngleThreshold)
597 {
598 btVector3 nearest;
599 btNearestPointInLineSegment(cp.m_localPointB, v1, v2, nearest);
600 btScalar len = (contact - nearest).length();
601 //
602 if (len < disttobestedge)
603 {
604 bestedge = 1;
605 disttobestedge = len;
606 }
607 }
608 // Edge 2 -> 0
609 if (btFabs(info->m_edgeV2V0Angle) < triangleInfoMapPtr->m_maxEdgeAngleThreshold)
610 {
611 btVector3 nearest;
612 btNearestPointInLineSegment(cp.m_localPointB, v2, v0, nearest);
613 btScalar len = (contact - nearest).length();
614 //
615 if (len < disttobestedge)
616 {
617 bestedge = 2;
618 disttobestedge = len;
619 }
620 }
621
622#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
623 btVector3 upfix = tri_normal * btVector3(0.1f, 0.1f, 0.1f);
624 btDebugDrawLine(tr * v0 + upfix, tr * v1 + upfix, red);
625#endif
626 if (btFabs(info->m_edgeV0V1Angle) < triangleInfoMapPtr->m_maxEdgeAngleThreshold)
627 {
628#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
629 btDebugDrawLine(tr * contact, tr * (contact + cp.m_normalWorldOnB * 10), black);
630#endif
631 btScalar len = (contact - nearest).length();
632 if (len < triangleInfoMapPtr->m_edgeDistanceThreshold)
633 if (bestedge == 0)
634 {
635 btVector3 edge(v0 - v1);
636 isNearEdge = true;
637
638 if (info->m_edgeV0V1Angle == btScalar(0))
639 {
641 }
642 else
643 {
646#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
647 btDebugDrawLine(tr * nearest, tr * (nearest + swapFactor * tri_normal * 10), white);
648#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
649
651
655 computedNormalB *= -1;
657
660 bool backFacingNormal = (NdotA < triangleInfoMapPtr->m_convexEpsilon) && (NdotB < triangleInfoMapPtr->m_convexEpsilon);
661
662#ifdef DEBUG_INTERNAL_EDGE
663 {
664 btDebugDrawLine(cp.getPositionWorldOnB(), cp.getPositionWorldOnB() + tr.getBasis() * (nB * 20), red);
665 }
666#endif //DEBUG_INTERNAL_EDGE
667
669 {
671 }
672 else
673 {
677 if (isClamped)
678 {
680 {
681 btVector3 newNormal = colObj0Wrap->getWorldTransform().getBasis() * clampedLocalNormal;
682 // cp.m_distance1 = cp.m_distance1 * newNormal.dot(cp.m_normalWorldOnB);
683 cp.m_normalWorldOnB = newNormal;
684 // Reproject collision point along normal. (what about cp.m_distance1?)
685 cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
686 cp.m_localPointB = colObj0Wrap->getWorldTransform().invXform(cp.m_positionWorldOnB);
687 }
688 }
689 }
690 }
691 }
692 }
693
694 btNearestPointInLineSegment(contact, v1, v2, nearest);
695#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
696 btDebugDrawLine(tr * nearest, tr * cp.m_localPointB, green);
697#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
698
699#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
700 btDebugDrawLine(tr * v1 + upfix, tr * v2 + upfix, green);
701#endif
702
703 if (btFabs(info->m_edgeV1V2Angle) < triangleInfoMapPtr->m_maxEdgeAngleThreshold)
704 {
705#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
706 btDebugDrawLine(tr * contact, tr * (contact + cp.m_normalWorldOnB * 10), black);
707#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
708
709 btScalar len = (contact - nearest).length();
710 if (len < triangleInfoMapPtr->m_edgeDistanceThreshold)
711 if (bestedge == 1)
712 {
713 isNearEdge = true;
714#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
715 btDebugDrawLine(tr * nearest, tr * (nearest + tri_normal * 10), white);
716#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
717
718 btVector3 edge(v1 - v2);
719
720 isNearEdge = true;
721
722 if (info->m_edgeV1V2Angle == btScalar(0))
723 {
725 }
726 else
727 {
728 bool isEdgeConvex = (info->m_flags & TRI_INFO_V1V2_CONVEX) != 0;
730#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
731 btDebugDrawLine(tr * nearest, tr * (nearest + swapFactor * tri_normal * 10), white);
732#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
733
735
739 computedNormalB *= -1;
741
742#ifdef DEBUG_INTERNAL_EDGE
743 {
744 btDebugDrawLine(cp.getPositionWorldOnB(), cp.getPositionWorldOnB() + tr.getBasis() * (nB * 20), red);
745 }
746#endif //DEBUG_INTERNAL_EDGE
747
750 bool backFacingNormal = (NdotA < triangleInfoMapPtr->m_convexEpsilon) && (NdotB < triangleInfoMapPtr->m_convexEpsilon);
751
753 {
755 }
756 else
757 {
759 btVector3 localContactNormalOnB = colObj0Wrap->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB;
762 if (isClamped)
763 {
765 {
766 btVector3 newNormal = colObj0Wrap->getWorldTransform().getBasis() * clampedLocalNormal;
767 // cp.m_distance1 = cp.m_distance1 * newNormal.dot(cp.m_normalWorldOnB);
768 cp.m_normalWorldOnB = newNormal;
769 // Reproject collision point along normal.
770 cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
771 cp.m_localPointB = colObj0Wrap->getWorldTransform().invXform(cp.m_positionWorldOnB);
772 }
773 }
774 }
775 }
776 }
777 }
778
779 btNearestPointInLineSegment(contact, v2, v0, nearest);
780#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
781 btDebugDrawLine(tr * nearest, tr * cp.m_localPointB, blue);
782#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
783#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
784 btDebugDrawLine(tr * v2 + upfix, tr * v0 + upfix, blue);
785#endif
786
787 if (btFabs(info->m_edgeV2V0Angle) < triangleInfoMapPtr->m_maxEdgeAngleThreshold)
788 {
789#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
790 btDebugDrawLine(tr * contact, tr * (contact + cp.m_normalWorldOnB * 10), black);
791#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
792
793 btScalar len = (contact - nearest).length();
794 if (len < triangleInfoMapPtr->m_edgeDistanceThreshold)
795 if (bestedge == 2)
796 {
797 isNearEdge = true;
798#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
799 btDebugDrawLine(tr * nearest, tr * (nearest + tri_normal * 10), white);
800#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
801
802 btVector3 edge(v2 - v0);
803
804 if (info->m_edgeV2V0Angle == btScalar(0))
805 {
807 }
808 else
809 {
810 bool isEdgeConvex = (info->m_flags & TRI_INFO_V2V0_CONVEX) != 0;
812#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
813 btDebugDrawLine(tr * nearest, tr * (nearest + swapFactor * tri_normal * 10), white);
814#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
815
820 computedNormalB *= -1;
822
823#ifdef DEBUG_INTERNAL_EDGE
824 {
825 btDebugDrawLine(cp.getPositionWorldOnB(), cp.getPositionWorldOnB() + tr.getBasis() * (nB * 20), red);
826 }
827#endif //DEBUG_INTERNAL_EDGE
828
831 bool backFacingNormal = (NdotA < triangleInfoMapPtr->m_convexEpsilon) && (NdotB < triangleInfoMapPtr->m_convexEpsilon);
832
834 {
836 }
837 else
838 {
840 // printf("hitting convex edge\n");
841
842 btVector3 localContactNormalOnB = colObj0Wrap->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB;
845 if (isClamped)
846 {
848 {
849 btVector3 newNormal = colObj0Wrap->getWorldTransform().getBasis() * clampedLocalNormal;
850 // cp.m_distance1 = cp.m_distance1 * newNormal.dot(cp.m_normalWorldOnB);
851 cp.m_normalWorldOnB = newNormal;
852 // Reproject collision point along normal.
853 cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
854 cp.m_localPointB = colObj0Wrap->getWorldTransform().invXform(cp.m_positionWorldOnB);
855 }
856 }
857 }
858 }
859 }
860 }
861
862#ifdef DEBUG_INTERNAL_EDGE
863 {
864 btVector3 color(0, 1, 1);
865 btDebugDrawLine(cp.getPositionWorldOnB(), cp.getPositionWorldOnB() + cp.m_normalWorldOnB * 10, color);
866 }
867#endif //DEBUG_INTERNAL_EDGE
868
869 if (isNearEdge)
870 {
871 if (numConcaveEdgeHits > 0)
872 {
874 {
875 //fix tri_normal so it pointing the same direction as the current local contact normal
877 {
878 tri_normal *= -1;
879 }
880 cp.m_normalWorldOnB = colObj0Wrap->getWorldTransform().getBasis() * tri_normal;
881 }
882 else
883 {
885 //if the tri_normal is pointing opposite direction as the current local contact normal, skip it
887 if (d < 0)
888 {
889 return;
890 }
891 //modify the normal to be the triangle normal (or backfacing normal)
892 cp.m_normalWorldOnB = colObj0Wrap->getWorldTransform().getBasis() * newNormal;
893 }
894
895 // Reproject collision point along normal.
896 cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
897 cp.m_localPointB = colObj0Wrap->getWorldTransform().invXform(cp.m_positionWorldOnB);
898 }
899 }
900}
@ SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE
@ TRIANGLE_SHAPE_PROXYTYPE
@ TRIANGLE_MESH_SHAPE_PROXYTYPE
@ TERRAIN_SHAPE_PROXYTYPE
PHY_ScalarType
PHY_ScalarType enumerates possible scalar types.
@ PHY_FLOAT
@ PHY_UCHAR
@ PHY_SHORT
@ PHY_INTEGER
static btScalar btGetAngle(const btVector3 &edgeA, const btVector3 &normalA, const btVector3 &normalB)
bool btClampNormal(const btVector3 &edge, const btVector3 &tri_normal_org, const btVector3 &localContactNormalOnB, btScalar correctedEdgeAngle, btVector3 &clampedLocalNormal)
void btAdjustInternalEdgeContacts(btManifoldPoint &cp, const btCollisionObjectWrapper *colObj0Wrap, const btCollisionObjectWrapper *colObj1Wrap, int partId0, int index0, int normalAdjustFlags)
Changes a btManifoldPoint collision normal to the normal from the mesh.
static int btGetHash(int partId, int triangleIndex)
void btGenerateInternalEdgeInfo(btBvhTriangleMeshShape *trimeshShape, btTriangleInfoMap *triangleInfoMap)
Call btGenerateInternalEdgeInfo to create triangle info, store in the shape 'userInfo'.
void btNearestPointInLineSegment(const btVector3 &point, const btVector3 &line0, const btVector3 &line1, btVector3 &nearestPoint)
@ BT_TRIANGLE_CONVEX_DOUBLE_SIDED
@ BT_TRIANGLE_CONVEX_BACKFACE_MODE
@ BT_TRIANGLE_CONCAVE_DOUBLE_SIDED
const T & btMax(const T &a, const T &b)
Definition btMinMax.h:27
#define MAX_NUM_PARTS_IN_BITS
btScalar dot(const btQuaternion &q1, const btQuaternion &q2)
Calculate the dot product between two quaternions.
btVector3 quatRotate(const btQuaternion &rotation, const btVector3 &v)
btScalar length(const btQuaternion &q)
Return the length of a quaternion.
#define SIMD_PI
Definition btScalar.h:526
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
Definition btScalar.h:314
#define BT_LARGE_FLOAT
Definition btScalar.h:316
btScalar btAtan2(btScalar x, btScalar y)
Definition btScalar.h:518
btScalar btFabs(btScalar x)
Definition btScalar.h:497
#define btAssert(x)
Definition btScalar.h:153
#define TRI_INFO_V1V2_CONVEX
#define TRI_INFO_V0V1_CONVEX
for btTriangleInfo m_flags
#define TRI_INFO_V2V0_CONVEX
#define TRI_INFO_V2V0_SWAP_NORMALB
#define TRI_INFO_V1V2_SWAP_NORMALB
#define TRI_INFO_V0V1_SWAP_NORMALB
The btBvhTriangleMeshShape is a static-triangle mesh shape, it can only be used for fixed/non-moving ...
const btTriangleInfoMap * getTriangleInfoMap() const
void insert(const Key &key, const Value &value)
Definition btHashMap.h:264
const Value * find(const Key &key) const
Definition btHashMap.h:424
btHeightfieldTerrainShape simulates a 2D heightfield terrain
const struct btTriangleInfoMap * getTriangleInfoMap() const
virtual void processAllTriangles(btTriangleCallback *callback, const btVector3 &aabbMin, const btVector3 &aabbMax) const
process all triangles within the provided axis-aligned bounding box
The btIDebugDraw interface class allows hooking up a debug renderer to visually debug simulations.
virtual void drawLine(const btVector3 &from, const btVector3 &to, const btVector3 &color)=0
ManifoldContactPoint collects and maintains persistent contactpoints.
The btMatrix3x3 class implements a 3x3 rotation matrix, to perform linear algebra in combination with...
Definition btMatrix3x3.h:50
The btQuaternion implements quaternion to perform linear algebra rotations in combination with btMatr...
The btScaledBvhTriangleMeshShape allows to instance a scaled version of an existing btBvhTriangleMesh...
The btStridingMeshInterface is the interface class for high performance generic access to triangle me...
The btTransform class supports rigid transforms with only translation and rotation and no scaling/she...
Definition btTransform.h:30
The btTriangleCallback provides a callback for each overlapping triangle when calling processAllTrian...
btVector3 can be used to represent 3D points and vectors.
Definition btVector3.h:82
btVector3 cross(const btVector3 &v) const
Return the cross product between this and another vector.
Definition btVector3.h:380
btScalar dot(const btVector3 &v) const
Return the dot product.
Definition btVector3.h:229
void setValue(const btScalar &_x, const btScalar &_y, const btScalar &_z)
Definition btVector3.h:640
btScalar length2() const
Return the length of the vector squared.
Definition btVector3.h:251
btVector3 & normalize()
Normalize this vector x^2 + y^2 + z^2 = 1.
Definition btVector3.h:303
virtual void processTriangle(btVector3 *triangle, int partId, int triangleIndex)
b3ProcessAllTrianglesHeightfield(btHeightfieldTerrainShape *heightFieldShape, btTriangleInfoMap *triangleInfoMap)
btHeightfieldTerrainShape * m_heightfieldShape
btTriangleInfoMap * m_triangleInfoMap
virtual void processTriangle(btVector3 *triangle, int partId, int triangleIndex)
The btTriangleInfoMap stores edge angle information for some triangles. You can compute this informat...
btScalar m_equalVertexThreshold
used to determine if a triangle edge is planar with zero angle
The btTriangleInfo structure stores information to adjust collision normals to avoid collisions again...