Blender  V3.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
20 static btIDebugDraw* gDebugDrawer = 0;
21 
22 void btSetDebugDrawer(btIDebugDraw* debugDrawer)
23 {
24  gDebugDrawer = debugDrawer;
25 }
26 
27 static 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 
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 static 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 {
51  int m_partIdA;
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 
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  {
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)
237  info->m_flags |= TRI_INFO_V0V1_CONVEX;
238  break;
239  }
240  case 2:
241  {
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)
259  info->m_flags |= TRI_INFO_V2V0_CONVEX;
260  break;
261  }
262  case 3:
263  {
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)
281  info->m_flags |= TRI_INFO_V1V2_CONVEX;
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.
429 void 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 
452 bool 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 
486 void 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;
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  {
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 }
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte blue
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei stride
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble green
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble v1
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 Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input 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 a producing a negative Combine Generate a color from its red
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Sky Generate a procedural sky texture Noise Generate fractal Perlin noise Wave Generate procedural bands or rings with noise Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a point
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 Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input 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 a color
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
btCollisionShape * getChildShape(int index)
PHY_ScalarType
@ PHY_FLOAT
@ PHY_UCHAR
@ PHY_SHORT
@ PHY_INTEGER
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 & 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
SIMD_FORCE_INLINE const btScalar & getY() const
Return the y value.
Definition: btQuadWord.h:101
#define MAX_NUM_PARTS_IN_BITS
SIMD_FORCE_INLINE btVector3 quatRotate(const btQuaternion &rotation, const btVector3 &v)
Definition: btQuaternion.h:926
#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
btTriangleShape()
SIMD_FORCE_INLINE btScalar length2() const
Return the length of the vector squared.
Definition: btVector3.h:251
SIMD_FORCE_INLINE btScalar angle(const btVector3 &v) const
Return the angle between this and another vector.
Definition: btVector3.h:356
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
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
const btVector3 & getPositionWorldOnB() const
btVector3 m_positionWorldOnA
m_positionWorldOnA is redundant information, see getPositionWorldOnA(), but for clarity
btVector3 m_localPointB
btVector3 m_normalWorldOnB
btVector3 m_positionWorldOnB
The btQuaternion implements quaternion to perform linear algebra rotations in combination with btMatr...
Definition: btQuaternion.h:50
StackEntry * from
int len
Definition: draw_manager.c:108
T dot(const vec_base< T, Size > &a, const vec_base< T, Size > &b)
vec_base< T, 3 > cross(const vec_base< T, 3 > &a, const vec_base< T, 3 > &b)
T length(const vec_base< T, Size > &a)
#define hash
Definition: noise.c:153
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
btScalar m_edgeV2V0Angle
btScalar m_edgeV0V1Angle
btScalar m_edgeV1V2Angle