Blender V4.3
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
22void btSetDebugDrawer(btIDebugDraw* debugDrawer)
23{
24 gDebugDrawer = debugDrawer;
25}
26
27static void btDebugDrawLine(const btVector3& from, const btVector3& to, const btVector3& color)
28{
29 if (gDebugDrawer)
30 gDebugDrawer->drawLine(from, to, color);
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
40static btScalar btGetAngle(const btVector3& edgeA, const btVector3& normalA, const btVector3& normalB)
41{
42 const btVector3 refAxis0 = edgeA;
43 const btVector3 refAxis1 = normalA;
44 const btVector3 swingAxis = normalB;
45 btScalar angle = btAtan2(swingAxis.dot(refAxis0), swingAxis.dot(refAxis1));
46 return angle;
47}
48
50{
55
56 virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
57 {
58 //skip self-collisions
59 if ((m_partIdA == partId) && (m_triangleIndexA == triangleIndex))
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",
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 {
100 sharedVertsA[numshared] = i;
101 sharedVertsB[numshared] = j;
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];
132 sharedVertsB[1] = sharedVertsB[0];
133 sharedVertsB[0] = tmp;
134 }
135
137
139 if (!info)
140 {
141 btTriangleInfo tmp;
143 info = m_triangleInfoMap->find(hash);
144 }
145
146 int sumvertsA = sharedVertsA[0] + sharedVertsA[1];
147 int otherIndexA = 3 - sumvertsA;
148
149 btVector3 edge(m_triangleVerticesA[sharedVertsA[1]] - m_triangleVerticesA[sharedVertsA[0]]);
150
151 btTriangleShape tA(m_triangleVerticesA[0], m_triangleVerticesA[1], m_triangleVerticesA[2]);
152 int otherIndexB = 3 - (sharedVertsB[0] + sharedVertsB[1]);
153
154 btTriangleShape tB(triangle[sharedVertsB[1]], triangle[sharedVertsB[0]], triangle[otherIndexB]);
155 //btTriangleShape tB(triangle[0],triangle[1],triangle[2]);
156
157 btVector3 normalA;
158 btVector3 normalB;
159 tA.calcNormal(normalA);
160 tB.calcNormal(normalB);
161 edge.normalize();
162 btVector3 edgeCrossA = edge.cross(normalA).normalize();
163
164 {
165 btVector3 tmp = m_triangleVerticesA[otherIndexA] - m_triangleVerticesA[sharedVertsA[0]];
166 if (edgeCrossA.dot(tmp) < 0)
167 {
168 edgeCrossA *= -1;
169 }
170 }
171
172 btVector3 edgeCrossB = edge.cross(normalB).normalize();
173
174 {
175 btVector3 tmp = triangle[otherIndexB] - triangle[sharedVertsB[0]];
176 if (edgeCrossB.dot(tmp) < 0)
177 {
178 edgeCrossB *= -1;
179 }
180 }
181
182 btScalar angle2 = 0;
183 btScalar ang4 = 0.f;
184
185 btVector3 calculatedEdge = edgeCrossA.cross(edgeCrossB);
186 btScalar len2 = calculatedEdge.length2();
187
188 btScalar correctedAngle(0);
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();
200 btVector3 calculatedNormalA = calculatedEdge.cross(edgeCrossA);
201 calculatedNormalA.normalize();
202 angle2 = btGetAngle(calculatedNormalA, edgeCrossA, edgeCrossB);
203 ang4 = SIMD_PI - angle2;
204 btScalar dotA = normalA.dot(edgeCrossB);
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 {
218 btVector3 edge = m_triangleVerticesA[0] - m_triangleVerticesA[1];
219 btQuaternion orn(edge, -correctedAngle);
220 btVector3 computedNormalB = quatRotate(orn, normalA);
221 btScalar bla = computedNormalB.dot(normalB);
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
234 info->m_edgeV0V1Angle = -correctedAngle;
235
236 if (isConvex)
238 break;
239 }
240 case 2:
241 {
242 btVector3 edge = m_triangleVerticesA[2] - m_triangleVerticesA[0];
243 btQuaternion orn(edge, -correctedAngle);
244 btVector3 computedNormalB = quatRotate(orn, normalA);
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
257 info->m_edgeV2V0Angle = -correctedAngle;
258 if (isConvex)
260 break;
261 }
262 case 3:
263 {
264 btVector3 edge = m_triangleVerticesA[1] - m_triangleVerticesA[2];
265 btQuaternion orn(edge, -correctedAngle);
266 btVector3 computedNormalB = quatRotate(orn, normalA);
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
278 info->m_edgeV1V2Angle = -correctedAngle;
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
304 :m_heightfieldShape(heightFieldShape),
305 m_triangleInfoMap(triangleInfoMap)
306 {
307 }
308 virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
309 {
310 btConnectivityProcessor connectivityProcessor;
311 connectivityProcessor.m_partIdA = partId;
312 connectivityProcessor.m_triangleIndexA = triangleIndex;
313 connectivityProcessor.m_triangleVerticesA = triangle;
314 connectivityProcessor.m_triangleInfoMap = m_triangleInfoMap;
315 btVector3 aabbMin, aabbMax;
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
325 m_heightfieldShape->processAllTriangles(&connectivityProcessor, aabbMin, aabbMax);
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
339 btStridingMeshInterface* meshInterface = trimeshShape->getMeshInterface();
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
354 btVector3 triangleVerts[3];
355 meshInterface->getLockedReadOnlyVertexIndexBase(&vertexbase, numverts, type, stride, &indexbase, indexstride, numfaces, indicestype, partId);
356 btVector3 aabbMin, aabbMax;
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);
374 triangleVerts[j] = btVector3(
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);
382 triangleVerts[j] = btVector3(btScalar(graphicsbase[0] * meshScaling.getX()), btScalar(graphicsbase[1] * meshScaling.getY()), btScalar(graphicsbase[2] * meshScaling.getZ()));
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
394 btConnectivityProcessor connectivityProcessor;
395 connectivityProcessor.m_partIdA = partId;
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
417 btVector3 aabbMin, aabbMax;
418
421
422 b3ProcessAllTrianglesHeightfield processHeightfield(heightfieldShape, triangleInfoMap);
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.
429void btNearestPointInLineSegment(const btVector3& point, const btVector3& line0, const btVector3& line1, btVector3& nearestPoint)
430{
431 btVector3 lineDelta = line1 - line0;
432
433 // Handle degenerate lines
434 if (lineDelta.fuzzyZero())
435 {
436 nearestPoint = line0;
437 }
438 else
439 {
440 btScalar delta = (point - line0).dot(lineDelta) / (lineDelta).dot(lineDelta);
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
448 nearestPoint = line0 + lineDelta * delta;
449 }
450}
451
452bool btClampNormal(const btVector3& edge, const btVector3& tri_normal_org, const btVector3& localContactNormalOnB, btScalar correctedEdgeAngle, btVector3& clampedLocalNormal)
453{
454 btVector3 tri_normal = tri_normal_org;
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
458 btVector3 edgeCross = edge.cross(tri_normal).normalize();
459 btScalar curAngle = btGetAngle(edgeCross, tri_normal, localContactNormalOnB);
460
461 if (correctedEdgeAngle < 0)
462 {
463 if (curAngle < correctedEdgeAngle)
464 {
465 btScalar diffAngle = correctedEdgeAngle - curAngle;
466 btQuaternion rotation(edge, diffAngle);
467 clampedLocalNormal = btMatrix3x3(rotation) * localContactNormalOnB;
468 return true;
469 }
470 }
471
472 if (correctedEdgeAngle >= 0)
473 {
474 if (curAngle > correctedEdgeAngle)
475 {
476 btScalar diffAngle = correctedEdgeAngle - curAngle;
477 btQuaternion rotation(edge, diffAngle);
478 clampedLocalNormal = btMatrix3x3(rotation) * localContactNormalOnB;
479 return true;
480 }
481 }
482 return false;
483}
484
486void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObjectWrapper* colObj0Wrap, const btCollisionObjectWrapper* colObj1Wrap, int partId0, int index0, int normalAdjustFlags)
487{
488 //btAssert(colObj0->getCollisionShape()->getShapeType() == TRIANGLE_SHAPE_PROXYTYPE);
489 if (colObj0Wrap->getCollisionShape()->getShapeType() != TRIANGLE_SHAPE_PROXYTYPE)
490 return;
491
492
493 btTriangleInfoMap* triangleInfoMapPtr = 0;
494
495 if (colObj0Wrap->getCollisionObject()->getCollisionShape()->getShapeType() == TERRAIN_SHAPE_PROXYTYPE)
496 {
497 btHeightfieldTerrainShape* heightfield = (btHeightfieldTerrainShape*)colObj0Wrap->getCollisionObject()->getCollisionShape();
498 triangleInfoMapPtr = heightfield->getTriangleInfoMap();
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());
505 btVector3 tri_normal;
506 tri_shape->calcNormal(tri_normal);
507 newNormal = 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?)
512 cp.m_localPointB = colObj0Wrap->getWorldTransform().invXform(cp.m_positionWorldOnB);
513 return;
514#endif
515 }
516
517
518 btBvhTriangleMeshShape* trimesh = 0;
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 {
533 triangleInfoMapPtr = (btTriangleInfoMap*)trimesh->getTriangleInfoMap();
534 }
535
536
537 if (!triangleInfoMapPtr)
538 return;
539
540 int hash = btGetHash(partId0, index0);
541
542 btTriangleInfo* info = triangleInfoMapPtr->find(hash);
543 if (!info)
544 return;
545
546 btScalar frontFacing = (normalAdjustFlags & BT_TRIANGLE_CONVEX_BACKFACE_MODE) == 0 ? 1.f : -1.f;
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);
557 btVector3 tri_normal;
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;
580 btScalar disttobestedge = BT_LARGE_FLOAT;
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;
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;
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 {
640 numConcaveEdgeHits++;
641 }
642 else
643 {
644 bool isEdgeConvex = (info->m_flags & TRI_INFO_V0V1_CONVEX);
645 btScalar swapFactor = isEdgeConvex ? btScalar(1) : btScalar(-1);
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
650 btVector3 nA = swapFactor * tri_normal;
651
652 btQuaternion orn(edge, info->m_edgeV0V1Angle);
653 btVector3 computedNormalB = quatRotate(orn, tri_normal);
655 computedNormalB *= -1;
656 btVector3 nB = swapFactor * computedNormalB;
657
658 btScalar NdotA = localContactNormalOnB.dot(nA);
659 btScalar NdotB = localContactNormalOnB.dot(nB);
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
668 if (backFacingNormal)
669 {
670 numConcaveEdgeHits++;
671 }
672 else
673 {
674 numConvexEdgeHits++;
675 btVector3 clampedLocalNormal;
676 bool isClamped = btClampNormal(edge, swapFactor * tri_normal, localContactNormalOnB, info->m_edgeV0V1Angle, clampedLocalNormal);
677 if (isClamped)
678 {
679 if (((normalAdjustFlags & BT_TRIANGLE_CONVEX_DOUBLE_SIDED) != 0) || (clampedLocalNormal.dot(frontFacing * tri_normal) > 0))
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?)
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 {
724 numConcaveEdgeHits++;
725 }
726 else
727 {
728 bool isEdgeConvex = (info->m_flags & TRI_INFO_V1V2_CONVEX) != 0;
729 btScalar swapFactor = isEdgeConvex ? btScalar(1) : btScalar(-1);
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
734 btVector3 nA = swapFactor * tri_normal;
735
736 btQuaternion orn(edge, info->m_edgeV1V2Angle);
737 btVector3 computedNormalB = quatRotate(orn, tri_normal);
739 computedNormalB *= -1;
740 btVector3 nB = swapFactor * computedNormalB;
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
748 btScalar NdotA = localContactNormalOnB.dot(nA);
749 btScalar NdotB = localContactNormalOnB.dot(nB);
750 bool backFacingNormal = (NdotA < triangleInfoMapPtr->m_convexEpsilon) && (NdotB < triangleInfoMapPtr->m_convexEpsilon);
751
752 if (backFacingNormal)
753 {
754 numConcaveEdgeHits++;
755 }
756 else
757 {
758 numConvexEdgeHits++;
759 btVector3 localContactNormalOnB = colObj0Wrap->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB;
760 btVector3 clampedLocalNormal;
761 bool isClamped = btClampNormal(edge, swapFactor * tri_normal, localContactNormalOnB, info->m_edgeV1V2Angle, clampedLocalNormal);
762 if (isClamped)
763 {
764 if (((normalAdjustFlags & BT_TRIANGLE_CONVEX_DOUBLE_SIDED) != 0) || (clampedLocalNormal.dot(frontFacing * tri_normal) > 0))
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.
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 {
806 numConcaveEdgeHits++;
807 }
808 else
809 {
810 bool isEdgeConvex = (info->m_flags & TRI_INFO_V2V0_CONVEX) != 0;
811 btScalar swapFactor = isEdgeConvex ? btScalar(1) : btScalar(-1);
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
816 btVector3 nA = swapFactor * tri_normal;
817 btQuaternion orn(edge, info->m_edgeV2V0Angle);
818 btVector3 computedNormalB = quatRotate(orn, tri_normal);
820 computedNormalB *= -1;
821 btVector3 nB = swapFactor * computedNormalB;
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
829 btScalar NdotA = localContactNormalOnB.dot(nA);
830 btScalar NdotB = localContactNormalOnB.dot(nB);
831 bool backFacingNormal = (NdotA < triangleInfoMapPtr->m_convexEpsilon) && (NdotB < triangleInfoMapPtr->m_convexEpsilon);
832
833 if (backFacingNormal)
834 {
835 numConcaveEdgeHits++;
836 }
837 else
838 {
839 numConvexEdgeHits++;
840 // printf("hitting convex edge\n");
841
842 btVector3 localContactNormalOnB = colObj0Wrap->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB;
843 btVector3 clampedLocalNormal;
844 bool isClamped = btClampNormal(edge, swapFactor * tri_normal, localContactNormalOnB, info->m_edgeV2V0Angle, clampedLocalNormal);
845 if (isClamped)
846 {
847 if (((normalAdjustFlags & BT_TRIANGLE_CONVEX_DOUBLE_SIDED) != 0) || (clampedLocalNormal.dot(frontFacing * tri_normal) > 0))
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.
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 {
873 if ((normalAdjustFlags & BT_TRIANGLE_CONCAVE_DOUBLE_SIDED) != 0)
874 {
875 //fix tri_normal so it pointing the same direction as the current local contact normal
876 if (tri_normal.dot(localContactNormalOnB) < 0)
877 {
878 tri_normal *= -1;
879 }
880 cp.m_normalWorldOnB = colObj0Wrap->getWorldTransform().getBasis() * tri_normal;
881 }
882 else
883 {
884 btVector3 newNormal = tri_normal * frontFacing;
885 //if the tri_normal is pointing opposite direction as the current local contact normal, skip it
886 btScalar d = newNormal.dot(localContactNormalOnB);
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.
897 cp.m_localPointB = colObj0Wrap->getWorldTransform().invXform(cp.m_positionWorldOnB);
898 }
899 }
900}
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
Definition IK_Math.h:125
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Brightness Control the brightness and contrast of the input color Vector Map input vector components with curves Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert Invert a producing a negative Combine Generate a color from its red
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Brightness Control the brightness and contrast of the input color Vector Map input vector components with curves Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert Invert a color
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Brightness Control the brightness and contrast of the input color Vector Map input vector components with curves Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert Invert a producing a negative Combine Generate a color from its green
ATTR_WARN_UNUSED_RESULT const BMVert * v2
@ SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE
@ TRIANGLE_SHAPE_PROXYTYPE
@ TRIANGLE_MESH_SHAPE_PROXYTYPE
@ TERRAIN_SHAPE_PROXYTYPE
btBvhTriangleMeshShape(btStridingMeshInterface *meshInterface, bool useQuantizedAabbCompression, bool buildBvh=true)
SIMD_FORCE_INLINE bool isConvex() const
PHY_ScalarType
@ PHY_FLOAT
@ PHY_UCHAR
@ PHY_SHORT
@ PHY_INTEGER
btConvexShape * getChildShape()
btHeightfieldTerrainShape(int heightStickWidth, int heightStickLength, const void *heightfieldData, btScalar heightScale, btScalar minHeight, btScalar maxHeight, int upAxis, PHY_ScalarType heightDataType, bool flipQuadEdges)
preferred constructor
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
btMatrix3x3
The btMatrix3x3 class implements a 3x3 rotation matrix, to perform linear algebra in combination with...
Definition btMatrix3x3.h:50
SIMD_FORCE_INLINE const btScalar & getY() const
Return the y value.
Definition btQuadWord.h:101
SIMD_FORCE_INLINE const btScalar & getZ() const
Return the z value.
Definition btQuadWord.h:103
SIMD_FORCE_INLINE const btScalar & getX() const
Return the x value.
Definition btQuadWord.h:99
#define MAX_NUM_PARTS_IN_BITS
SIMD_FORCE_INLINE btVector3 quatRotate(const btQuaternion &rotation, const btVector3 &v)
#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
SIMD_FORCE_INLINE btScalar btFabs(btScalar x)
Definition btScalar.h:497
SIMD_FORCE_INLINE btScalar btAtan2(btScalar x, btScalar y)
Definition btScalar.h:518
#define btAssert(x)
Definition btScalar.h:295
btScaledBvhTriangleMeshShape(btBvhTriangleMeshShape *childShape, const btVector3 &localScaling)
btStridingMeshInterface
btTransform
The btTransform class supports rigid transforms with only translation and rotation and no scaling/she...
Definition btTransform.h:30
#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
SIMD_FORCE_INLINE btScalar length2() const
Return the length of the vector squared.
Definition btVector3.h:251
btVector3
btVector3 can be used to represent 3D points and vectors. It has an un-used w component to suit 16-by...
Definition btVector3.h:82
SIMD_FORCE_INLINE btScalar length() const
Return the length of the vector.
Definition btVector3.h:257
btScalar m_equalVertexThreshold
void insert(const Key &key, const Value &value)
Definition btHashMap.h:264
const Value * find(const Key &key) const
Definition btHashMap.h:424
virtual void drawLine(const btVector3 &from, const btVector3 &to, const btVector3 &color)=0
btVector3 m_positionWorldOnA
m_positionWorldOnA is redundant information, see getPositionWorldOnA(), but for clarity
btVector3 m_localPointB
const btVector3 & getPositionWorldOnB() const
btVector3 m_normalWorldOnB
btVector3 m_positionWorldOnB
The btQuaternion implements quaternion to perform linear algebra rotations in combination with btMatr...
additional_info("compositor_sum_squared_difference_float_shared") .push_constant(Type output_img float dot(value.rgb, luminance_coefficients)") .define("LOAD(value)"
#define printf
int len
ccl_device_inline float cross(const float2 a, const float2 b)
#define hash
Definition noise.c:154
virtual void processTriangle(btVector3 *triangle, int partId, int triangleIndex)
b3ProcessAllTrianglesHeightfield(btHeightfieldTerrainShape *heightFieldShape, btTriangleInfoMap *triangleInfoMap)
btHeightfieldTerrainShape * m_heightfieldShape
SIMD_FORCE_INLINE const btCollisionShape * getCollisionShape() const
SIMD_FORCE_INLINE const btTransform & getWorldTransform() const
SIMD_FORCE_INLINE const btCollisionObject * getCollisionObject() const
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_maxEdgeAngleThreshold
used to determine edge contacts: if the closest distance between a contact point and an edge is small...
btScalar m_equalVertexThreshold
used to determine if a triangle edge is planar with zero angle