summaryrefslogtreecommitdiff
path: root/thirdparty/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp')
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp900
1 files changed, 0 insertions, 900 deletions
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp
deleted file mode 100644
index a71700f58a..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp
+++ /dev/null
@@ -1,900 +0,0 @@
-#include "btInternalEdgeUtility.h"
-
-#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
-#include "BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h"
-
-#include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h"
-#include "BulletCollision/CollisionShapes/btTriangleShape.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
-#include "BulletCollision/NarrowPhaseCollision/btManifoldPoint.h"
-#include "LinearMath/btIDebugDraw.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
-
-//#define DEBUG_INTERNAL_EDGE
-
-#ifdef DEBUG_INTERNAL_EDGE
-#include <stdio.h>
-#endif //DEBUG_INTERNAL_EDGE
-
-#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
-static btIDebugDraw* gDebugDrawer = 0;
-
-void btSetDebugDrawer(btIDebugDraw* debugDrawer)
-{
- gDebugDrawer = debugDrawer;
-}
-
-static void btDebugDrawLine(const btVector3& from, const btVector3& to, const btVector3& color)
-{
- if (gDebugDrawer)
- gDebugDrawer->drawLine(from, to, color);
-}
-#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
-
-static int btGetHash(int partId, int triangleIndex)
-{
- int hash = (partId << (31 - MAX_NUM_PARTS_IN_BITS)) | triangleIndex;
- return hash;
-}
-
-static btScalar btGetAngle(const btVector3& edgeA, const btVector3& normalA, const btVector3& normalB)
-{
- const btVector3 refAxis0 = edgeA;
- const btVector3 refAxis1 = normalA;
- const btVector3 swingAxis = normalB;
- btScalar angle = btAtan2(swingAxis.dot(refAxis0), swingAxis.dot(refAxis1));
- return angle;
-}
-
-struct btConnectivityProcessor : public btTriangleCallback
-{
- int m_partIdA;
- int m_triangleIndexA;
- btVector3* m_triangleVerticesA;
- btTriangleInfoMap* m_triangleInfoMap;
-
- virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
- {
- //skip self-collisions
- if ((m_partIdA == partId) && (m_triangleIndexA == triangleIndex))
- return;
-
- //skip duplicates (disabled for now)
- //if ((m_partIdA <= partId) && (m_triangleIndexA <= triangleIndex))
- // return;
-
- //search for shared vertices and edges
- int numshared = 0;
- int sharedVertsA[3] = {-1, -1, -1};
- int sharedVertsB[3] = {-1, -1, -1};
-
- ///skip degenerate triangles
- btScalar crossBSqr = ((triangle[1] - triangle[0]).cross(triangle[2] - triangle[0])).length2();
- if (crossBSqr < m_triangleInfoMap->m_equalVertexThreshold)
- return;
-
- btScalar crossASqr = ((m_triangleVerticesA[1] - m_triangleVerticesA[0]).cross(m_triangleVerticesA[2] - m_triangleVerticesA[0])).length2();
- ///skip degenerate triangles
- if (crossASqr < m_triangleInfoMap->m_equalVertexThreshold)
- return;
-
-#if 0
- printf("triangle A[0] = (%f,%f,%f)\ntriangle A[1] = (%f,%f,%f)\ntriangle A[2] = (%f,%f,%f)\n",
- m_triangleVerticesA[0].getX(),m_triangleVerticesA[0].getY(),m_triangleVerticesA[0].getZ(),
- m_triangleVerticesA[1].getX(),m_triangleVerticesA[1].getY(),m_triangleVerticesA[1].getZ(),
- m_triangleVerticesA[2].getX(),m_triangleVerticesA[2].getY(),m_triangleVerticesA[2].getZ());
-
- printf("partId=%d, triangleIndex=%d\n",partId,triangleIndex);
- printf("triangle B[0] = (%f,%f,%f)\ntriangle B[1] = (%f,%f,%f)\ntriangle B[2] = (%f,%f,%f)\n",
- triangle[0].getX(),triangle[0].getY(),triangle[0].getZ(),
- triangle[1].getX(),triangle[1].getY(),triangle[1].getZ(),
- triangle[2].getX(),triangle[2].getY(),triangle[2].getZ());
-#endif
-
- for (int i = 0; i < 3; i++)
- {
- for (int j = 0; j < 3; j++)
- {
- if ((m_triangleVerticesA[i] - triangle[j]).length2() < m_triangleInfoMap->m_equalVertexThreshold)
- {
- sharedVertsA[numshared] = i;
- sharedVertsB[numshared] = j;
- numshared++;
- ///degenerate case
- if (numshared >= 3)
- return;
- }
- }
- ///degenerate case
- if (numshared >= 3)
- return;
- }
- switch (numshared)
- {
- case 0:
- {
- break;
- }
- case 1:
- {
- //shared vertex
- break;
- }
- case 2:
- {
- //shared edge
- //we need to make sure the edge is in the order V2V0 and not V0V2 so that the signs are correct
- if (sharedVertsA[0] == 0 && sharedVertsA[1] == 2)
- {
- sharedVertsA[0] = 2;
- sharedVertsA[1] = 0;
- int tmp = sharedVertsB[1];
- sharedVertsB[1] = sharedVertsB[0];
- sharedVertsB[0] = tmp;
- }
-
- int hash = btGetHash(m_partIdA, m_triangleIndexA);
-
- btTriangleInfo* info = m_triangleInfoMap->find(hash);
- if (!info)
- {
- btTriangleInfo tmp;
- m_triangleInfoMap->insert(hash, tmp);
- info = m_triangleInfoMap->find(hash);
- }
-
- int sumvertsA = sharedVertsA[0] + sharedVertsA[1];
- int otherIndexA = 3 - sumvertsA;
-
- btVector3 edge(m_triangleVerticesA[sharedVertsA[1]] - m_triangleVerticesA[sharedVertsA[0]]);
-
- btTriangleShape tA(m_triangleVerticesA[0], m_triangleVerticesA[1], m_triangleVerticesA[2]);
- int otherIndexB = 3 - (sharedVertsB[0] + sharedVertsB[1]);
-
- btTriangleShape tB(triangle[sharedVertsB[1]], triangle[sharedVertsB[0]], triangle[otherIndexB]);
- //btTriangleShape tB(triangle[0],triangle[1],triangle[2]);
-
- btVector3 normalA;
- btVector3 normalB;
- tA.calcNormal(normalA);
- tB.calcNormal(normalB);
- edge.normalize();
- btVector3 edgeCrossA = edge.cross(normalA).normalize();
-
- {
- btVector3 tmp = m_triangleVerticesA[otherIndexA] - m_triangleVerticesA[sharedVertsA[0]];
- if (edgeCrossA.dot(tmp) < 0)
- {
- edgeCrossA *= -1;
- }
- }
-
- btVector3 edgeCrossB = edge.cross(normalB).normalize();
-
- {
- btVector3 tmp = triangle[otherIndexB] - triangle[sharedVertsB[0]];
- if (edgeCrossB.dot(tmp) < 0)
- {
- edgeCrossB *= -1;
- }
- }
-
- btScalar angle2 = 0;
- btScalar ang4 = 0.f;
-
- btVector3 calculatedEdge = edgeCrossA.cross(edgeCrossB);
- btScalar len2 = calculatedEdge.length2();
-
- btScalar correctedAngle(0);
- //btVector3 calculatedNormalB = normalA;
- bool isConvex = false;
-
- if (len2 < m_triangleInfoMap->m_planarEpsilon)
- {
- angle2 = 0.f;
- ang4 = 0.f;
- }
- else
- {
- calculatedEdge.normalize();
- btVector3 calculatedNormalA = calculatedEdge.cross(edgeCrossA);
- calculatedNormalA.normalize();
- angle2 = btGetAngle(calculatedNormalA, edgeCrossA, edgeCrossB);
- ang4 = SIMD_PI - angle2;
- btScalar dotA = normalA.dot(edgeCrossB);
- ///@todo: check if we need some epsilon, due to floating point imprecision
- isConvex = (dotA < 0.);
-
- correctedAngle = isConvex ? ang4 : -ang4;
- }
-
- //alternatively use
- //btVector3 calculatedNormalB2 = quatRotate(orn,normalA);
-
- switch (sumvertsA)
- {
- case 1:
- {
- btVector3 edge = m_triangleVerticesA[0] - m_triangleVerticesA[1];
- btQuaternion orn(edge, -correctedAngle);
- btVector3 computedNormalB = quatRotate(orn, normalA);
- btScalar bla = computedNormalB.dot(normalB);
- if (bla < 0)
- {
- computedNormalB *= -1;
- info->m_flags |= TRI_INFO_V0V1_SWAP_NORMALB;
- }
-#ifdef DEBUG_INTERNAL_EDGE
- if ((computedNormalB - normalB).length() > 0.0001)
- {
- printf("warning: normals not identical\n");
- }
-#endif //DEBUG_INTERNAL_EDGE
-
- info->m_edgeV0V1Angle = -correctedAngle;
-
- if (isConvex)
- info->m_flags |= TRI_INFO_V0V1_CONVEX;
- break;
- }
- case 2:
- {
- btVector3 edge = m_triangleVerticesA[2] - m_triangleVerticesA[0];
- btQuaternion orn(edge, -correctedAngle);
- btVector3 computedNormalB = quatRotate(orn, normalA);
- if (computedNormalB.dot(normalB) < 0)
- {
- computedNormalB *= -1;
- info->m_flags |= TRI_INFO_V2V0_SWAP_NORMALB;
- }
-
-#ifdef DEBUG_INTERNAL_EDGE
- if ((computedNormalB - normalB).length() > 0.0001)
- {
- printf("warning: normals not identical\n");
- }
-#endif //DEBUG_INTERNAL_EDGE
- info->m_edgeV2V0Angle = -correctedAngle;
- if (isConvex)
- info->m_flags |= TRI_INFO_V2V0_CONVEX;
- break;
- }
- case 3:
- {
- btVector3 edge = m_triangleVerticesA[1] - m_triangleVerticesA[2];
- btQuaternion orn(edge, -correctedAngle);
- btVector3 computedNormalB = quatRotate(orn, normalA);
- if (computedNormalB.dot(normalB) < 0)
- {
- info->m_flags |= TRI_INFO_V1V2_SWAP_NORMALB;
- computedNormalB *= -1;
- }
-#ifdef DEBUG_INTERNAL_EDGE
- if ((computedNormalB - normalB).length() > 0.0001)
- {
- printf("warning: normals not identical\n");
- }
-#endif //DEBUG_INTERNAL_EDGE
- info->m_edgeV1V2Angle = -correctedAngle;
-
- if (isConvex)
- info->m_flags |= TRI_INFO_V1V2_CONVEX;
- break;
- }
- }
-
- break;
- }
- default:
- {
- // printf("warning: duplicate triangle\n");
- }
- }
- }
-};
-
-
-struct b3ProcessAllTrianglesHeightfield: public btTriangleCallback
-{
- btHeightfieldTerrainShape* m_heightfieldShape;
- btTriangleInfoMap* m_triangleInfoMap;
-
-
- b3ProcessAllTrianglesHeightfield(btHeightfieldTerrainShape* heightFieldShape, btTriangleInfoMap* triangleInfoMap)
- :m_heightfieldShape(heightFieldShape),
- m_triangleInfoMap(triangleInfoMap)
- {
- }
- virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
- {
- btConnectivityProcessor connectivityProcessor;
- connectivityProcessor.m_partIdA = partId;
- connectivityProcessor.m_triangleIndexA = triangleIndex;
- connectivityProcessor.m_triangleVerticesA = triangle;
- connectivityProcessor.m_triangleInfoMap = m_triangleInfoMap;
- btVector3 aabbMin, aabbMax;
- aabbMin.setValue(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
- aabbMax.setValue(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
- aabbMin.setMin(triangle[0]);
- aabbMax.setMax(triangle[0]);
- aabbMin.setMin(triangle[1]);
- aabbMax.setMax(triangle[1]);
- aabbMin.setMin(triangle[2]);
- aabbMax.setMax(triangle[2]);
-
- m_heightfieldShape->processAllTriangles(&connectivityProcessor, aabbMin, aabbMax);
- }
-};
-/////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////
-
-void btGenerateInternalEdgeInfo(btBvhTriangleMeshShape* trimeshShape, btTriangleInfoMap* triangleInfoMap)
-{
- //the user pointer shouldn't already be used for other purposes, we intend to store connectivity info there!
- if (trimeshShape->getTriangleInfoMap())
- return;
-
- trimeshShape->setTriangleInfoMap(triangleInfoMap);
-
- btStridingMeshInterface* meshInterface = trimeshShape->getMeshInterface();
- const btVector3& meshScaling = meshInterface->getScaling();
-
- for (int partId = 0; partId < meshInterface->getNumSubParts(); partId++)
- {
- const unsigned char* vertexbase = 0;
- int numverts = 0;
- PHY_ScalarType type = PHY_INTEGER;
- int stride = 0;
- const unsigned char* indexbase = 0;
- int indexstride = 0;
- int numfaces = 0;
- PHY_ScalarType indicestype = PHY_INTEGER;
- //PHY_ScalarType indexType=0;
-
- btVector3 triangleVerts[3];
- meshInterface->getLockedReadOnlyVertexIndexBase(&vertexbase, numverts, type, stride, &indexbase, indexstride, numfaces, indicestype, partId);
- btVector3 aabbMin, aabbMax;
-
- for (int triangleIndex = 0; triangleIndex < numfaces; triangleIndex++)
- {
- unsigned int* gfxbase = (unsigned int*)(indexbase + triangleIndex * indexstride);
-
- for (int j = 2; j >= 0; j--)
- {
- int graphicsindex;
- switch (indicestype) {
- case PHY_INTEGER: graphicsindex = gfxbase[j]; break;
- case PHY_SHORT: graphicsindex = ((unsigned short*)gfxbase)[j]; break;
- case PHY_UCHAR: graphicsindex = ((unsigned char*)gfxbase)[j]; break;
- default: btAssert(0);
- }
- if (type == PHY_FLOAT)
- {
- float* graphicsbase = (float*)(vertexbase + graphicsindex * stride);
- triangleVerts[j] = btVector3(
- graphicsbase[0] * meshScaling.getX(),
- graphicsbase[1] * meshScaling.getY(),
- graphicsbase[2] * meshScaling.getZ());
- }
- else
- {
- double* graphicsbase = (double*)(vertexbase + graphicsindex * stride);
- triangleVerts[j] = btVector3(btScalar(graphicsbase[0] * meshScaling.getX()), btScalar(graphicsbase[1] * meshScaling.getY()), btScalar(graphicsbase[2] * meshScaling.getZ()));
- }
- }
- aabbMin.setValue(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
- aabbMax.setValue(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
- aabbMin.setMin(triangleVerts[0]);
- aabbMax.setMax(triangleVerts[0]);
- aabbMin.setMin(triangleVerts[1]);
- aabbMax.setMax(triangleVerts[1]);
- aabbMin.setMin(triangleVerts[2]);
- aabbMax.setMax(triangleVerts[2]);
-
- btConnectivityProcessor connectivityProcessor;
- connectivityProcessor.m_partIdA = partId;
- connectivityProcessor.m_triangleIndexA = triangleIndex;
- connectivityProcessor.m_triangleVerticesA = &triangleVerts[0];
- connectivityProcessor.m_triangleInfoMap = triangleInfoMap;
-
- trimeshShape->processAllTriangles(&connectivityProcessor, aabbMin, aabbMax);
- }
- }
-}
-
-
-void btGenerateInternalEdgeInfo(btHeightfieldTerrainShape* heightfieldShape, btTriangleInfoMap* triangleInfoMap)
-{
-
- //the user pointer shouldn't already be used for other purposes, we intend to store connectivity info there!
- if (heightfieldShape->getTriangleInfoMap())
- return;
-
- heightfieldShape->setTriangleInfoMap(triangleInfoMap);
-
- //get all the triangles of the heightfield
-
- btVector3 aabbMin, aabbMax;
-
- aabbMax.setValue(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
- aabbMin.setValue(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
-
- b3ProcessAllTrianglesHeightfield processHeightfield(heightfieldShape, triangleInfoMap);
- heightfieldShape->processAllTriangles(&processHeightfield, aabbMin, aabbMax);
-
-}
-
-// Given a point and a line segment (defined by two points), compute the closest point
-// in the line. Cap the point at the endpoints of the line segment.
-void btNearestPointInLineSegment(const btVector3& point, const btVector3& line0, const btVector3& line1, btVector3& nearestPoint)
-{
- btVector3 lineDelta = line1 - line0;
-
- // Handle degenerate lines
- if (lineDelta.fuzzyZero())
- {
- nearestPoint = line0;
- }
- else
- {
- btScalar delta = (point - line0).dot(lineDelta) / (lineDelta).dot(lineDelta);
-
- // Clamp the point to conform to the segment's endpoints
- if (delta < 0)
- delta = 0;
- else if (delta > 1)
- delta = 1;
-
- nearestPoint = line0 + lineDelta * delta;
- }
-}
-
-bool btClampNormal(const btVector3& edge, const btVector3& tri_normal_org, const btVector3& localContactNormalOnB, btScalar correctedEdgeAngle, btVector3& clampedLocalNormal)
-{
- btVector3 tri_normal = tri_normal_org;
- //we only have a local triangle normal, not a local contact normal -> only normal in world space...
- //either compute the current angle all in local space, or all in world space
-
- btVector3 edgeCross = edge.cross(tri_normal).normalize();
- btScalar curAngle = btGetAngle(edgeCross, tri_normal, localContactNormalOnB);
-
- if (correctedEdgeAngle < 0)
- {
- if (curAngle < correctedEdgeAngle)
- {
- btScalar diffAngle = correctedEdgeAngle - curAngle;
- btQuaternion rotation(edge, diffAngle);
- clampedLocalNormal = btMatrix3x3(rotation) * localContactNormalOnB;
- return true;
- }
- }
-
- if (correctedEdgeAngle >= 0)
- {
- if (curAngle > correctedEdgeAngle)
- {
- btScalar diffAngle = correctedEdgeAngle - curAngle;
- btQuaternion rotation(edge, diffAngle);
- clampedLocalNormal = btMatrix3x3(rotation) * localContactNormalOnB;
- return true;
- }
- }
- return false;
-}
-
-/// Changes a btManifoldPoint collision normal to the normal from the mesh.
-void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObjectWrapper* colObj0Wrap, const btCollisionObjectWrapper* colObj1Wrap, int partId0, int index0, int normalAdjustFlags)
-{
- //btAssert(colObj0->getCollisionShape()->getShapeType() == TRIANGLE_SHAPE_PROXYTYPE);
- if (colObj0Wrap->getCollisionShape()->getShapeType() != TRIANGLE_SHAPE_PROXYTYPE)
- return;
-
-
- btTriangleInfoMap* triangleInfoMapPtr = 0;
-
- if (colObj0Wrap->getCollisionObject()->getCollisionShape()->getShapeType() == TERRAIN_SHAPE_PROXYTYPE)
- {
- btHeightfieldTerrainShape* heightfield = (btHeightfieldTerrainShape*)colObj0Wrap->getCollisionObject()->getCollisionShape();
- triangleInfoMapPtr = heightfield->getTriangleInfoMap();
-
-//#define USE_HEIGHTFIELD_TRIANGLES
-#ifdef USE_HEIGHTFIELD_TRIANGLES
- btVector3 newNormal = btVector3(0, 0, 1);
-
- const btTriangleShape* tri_shape = static_cast<const btTriangleShape*>(colObj0Wrap->getCollisionShape());
- btVector3 tri_normal;
- tri_shape->calcNormal(tri_normal);
- newNormal = tri_normal;
- // cp.m_distance1 = cp.m_distance1 * newNormal.dot(cp.m_normalWorldOnB);
- cp.m_normalWorldOnB = newNormal;
- // Reproject collision point along normal. (what about cp.m_distance1?)
- cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
- cp.m_localPointB = colObj0Wrap->getWorldTransform().invXform(cp.m_positionWorldOnB);
- return;
-#endif
- }
-
-
- btBvhTriangleMeshShape* trimesh = 0;
-
- if (colObj0Wrap->getCollisionObject()->getCollisionShape()->getShapeType() == SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE)
- {
- trimesh = ((btScaledBvhTriangleMeshShape*)colObj0Wrap->getCollisionObject()->getCollisionShape())->getChildShape();
- }
- else
- {
- if (colObj0Wrap->getCollisionObject()->getCollisionShape()->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
- {
- trimesh = (btBvhTriangleMeshShape*)colObj0Wrap->getCollisionObject()->getCollisionShape();
- }
- }
- if (trimesh)
- {
- triangleInfoMapPtr = (btTriangleInfoMap*)trimesh->getTriangleInfoMap();
- }
-
-
- if (!triangleInfoMapPtr)
- return;
-
- int hash = btGetHash(partId0, index0);
-
- btTriangleInfo* info = triangleInfoMapPtr->find(hash);
- if (!info)
- return;
-
- btScalar frontFacing = (normalAdjustFlags & BT_TRIANGLE_CONVEX_BACKFACE_MODE) == 0 ? 1.f : -1.f;
-
- const btTriangleShape* tri_shape = static_cast<const btTriangleShape*>(colObj0Wrap->getCollisionShape());
- btVector3 v0, v1, v2;
- tri_shape->getVertex(0, v0);
- tri_shape->getVertex(1, v1);
- tri_shape->getVertex(2, v2);
-
- //btVector3 center = (v0+v1+v2)*btScalar(1./3.);
-
- btVector3 red(1, 0, 0), green(0, 1, 0), blue(0, 0, 1), white(1, 1, 1), black(0, 0, 0);
- btVector3 tri_normal;
- tri_shape->calcNormal(tri_normal);
-
- //btScalar dot = tri_normal.dot(cp.m_normalWorldOnB);
- btVector3 nearest;
- btNearestPointInLineSegment(cp.m_localPointB, v0, v1, nearest);
-
- btVector3 contact = cp.m_localPointB;
-#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
- const btTransform& tr = colObj0->getWorldTransform();
- btDebugDrawLine(tr * nearest, tr * cp.m_localPointB, red);
-#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
-
- bool isNearEdge = false;
-
- int numConcaveEdgeHits = 0;
- int numConvexEdgeHits = 0;
-
- btVector3 localContactNormalOnB = colObj0Wrap->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB;
- localContactNormalOnB.normalize(); //is this necessary?
-
- // Get closest edge
- int bestedge = -1;
- btScalar disttobestedge = BT_LARGE_FLOAT;
- //
- // Edge 0 -> 1
- if (btFabs(info->m_edgeV0V1Angle) < triangleInfoMapPtr->m_maxEdgeAngleThreshold)
- {
- btVector3 nearest;
- btNearestPointInLineSegment(cp.m_localPointB, v0, v1, nearest);
- btScalar len = (contact - nearest).length();
- //
- if (len < disttobestedge)
- {
- bestedge = 0;
- disttobestedge = len;
- }
- }
- // Edge 1 -> 2
- if (btFabs(info->m_edgeV1V2Angle) < triangleInfoMapPtr->m_maxEdgeAngleThreshold)
- {
- btVector3 nearest;
- btNearestPointInLineSegment(cp.m_localPointB, v1, v2, nearest);
- btScalar len = (contact - nearest).length();
- //
- if (len < disttobestedge)
- {
- bestedge = 1;
- disttobestedge = len;
- }
- }
- // Edge 2 -> 0
- if (btFabs(info->m_edgeV2V0Angle) < triangleInfoMapPtr->m_maxEdgeAngleThreshold)
- {
- btVector3 nearest;
- btNearestPointInLineSegment(cp.m_localPointB, v2, v0, nearest);
- btScalar len = (contact - nearest).length();
- //
- if (len < disttobestedge)
- {
- bestedge = 2;
- disttobestedge = len;
- }
- }
-
-#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
- btVector3 upfix = tri_normal * btVector3(0.1f, 0.1f, 0.1f);
- btDebugDrawLine(tr * v0 + upfix, tr * v1 + upfix, red);
-#endif
- if (btFabs(info->m_edgeV0V1Angle) < triangleInfoMapPtr->m_maxEdgeAngleThreshold)
- {
-#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
- btDebugDrawLine(tr * contact, tr * (contact + cp.m_normalWorldOnB * 10), black);
-#endif
- btScalar len = (contact - nearest).length();
- if (len < triangleInfoMapPtr->m_edgeDistanceThreshold)
- if (bestedge == 0)
- {
- btVector3 edge(v0 - v1);
- isNearEdge = true;
-
- if (info->m_edgeV0V1Angle == btScalar(0))
- {
- numConcaveEdgeHits++;
- }
- else
- {
- bool isEdgeConvex = (info->m_flags & TRI_INFO_V0V1_CONVEX);
- btScalar swapFactor = isEdgeConvex ? btScalar(1) : btScalar(-1);
-#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
- btDebugDrawLine(tr * nearest, tr * (nearest + swapFactor * tri_normal * 10), white);
-#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
-
- btVector3 nA = swapFactor * tri_normal;
-
- btQuaternion orn(edge, info->m_edgeV0V1Angle);
- btVector3 computedNormalB = quatRotate(orn, tri_normal);
- if (info->m_flags & TRI_INFO_V0V1_SWAP_NORMALB)
- computedNormalB *= -1;
- btVector3 nB = swapFactor * computedNormalB;
-
- btScalar NdotA = localContactNormalOnB.dot(nA);
- btScalar NdotB = localContactNormalOnB.dot(nB);
- bool backFacingNormal = (NdotA < triangleInfoMapPtr->m_convexEpsilon) && (NdotB < triangleInfoMapPtr->m_convexEpsilon);
-
-#ifdef DEBUG_INTERNAL_EDGE
- {
- btDebugDrawLine(cp.getPositionWorldOnB(), cp.getPositionWorldOnB() + tr.getBasis() * (nB * 20), red);
- }
-#endif //DEBUG_INTERNAL_EDGE
-
- if (backFacingNormal)
- {
- numConcaveEdgeHits++;
- }
- else
- {
- numConvexEdgeHits++;
- btVector3 clampedLocalNormal;
- bool isClamped = btClampNormal(edge, swapFactor * tri_normal, localContactNormalOnB, info->m_edgeV0V1Angle, clampedLocalNormal);
- if (isClamped)
- {
- if (((normalAdjustFlags & BT_TRIANGLE_CONVEX_DOUBLE_SIDED) != 0) || (clampedLocalNormal.dot(frontFacing * tri_normal) > 0))
- {
- btVector3 newNormal = colObj0Wrap->getWorldTransform().getBasis() * clampedLocalNormal;
- // cp.m_distance1 = cp.m_distance1 * newNormal.dot(cp.m_normalWorldOnB);
- cp.m_normalWorldOnB = newNormal;
- // Reproject collision point along normal. (what about cp.m_distance1?)
- cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
- cp.m_localPointB = colObj0Wrap->getWorldTransform().invXform(cp.m_positionWorldOnB);
- }
- }
- }
- }
- }
- }
-
- btNearestPointInLineSegment(contact, v1, v2, nearest);
-#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
- btDebugDrawLine(tr * nearest, tr * cp.m_localPointB, green);
-#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
-
-#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
- btDebugDrawLine(tr * v1 + upfix, tr * v2 + upfix, green);
-#endif
-
- if (btFabs(info->m_edgeV1V2Angle) < triangleInfoMapPtr->m_maxEdgeAngleThreshold)
- {
-#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
- btDebugDrawLine(tr * contact, tr * (contact + cp.m_normalWorldOnB * 10), black);
-#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
-
- btScalar len = (contact - nearest).length();
- if (len < triangleInfoMapPtr->m_edgeDistanceThreshold)
- if (bestedge == 1)
- {
- isNearEdge = true;
-#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
- btDebugDrawLine(tr * nearest, tr * (nearest + tri_normal * 10), white);
-#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
-
- btVector3 edge(v1 - v2);
-
- isNearEdge = true;
-
- if (info->m_edgeV1V2Angle == btScalar(0))
- {
- numConcaveEdgeHits++;
- }
- else
- {
- bool isEdgeConvex = (info->m_flags & TRI_INFO_V1V2_CONVEX) != 0;
- btScalar swapFactor = isEdgeConvex ? btScalar(1) : btScalar(-1);
-#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
- btDebugDrawLine(tr * nearest, tr * (nearest + swapFactor * tri_normal * 10), white);
-#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
-
- btVector3 nA = swapFactor * tri_normal;
-
- btQuaternion orn(edge, info->m_edgeV1V2Angle);
- btVector3 computedNormalB = quatRotate(orn, tri_normal);
- if (info->m_flags & TRI_INFO_V1V2_SWAP_NORMALB)
- computedNormalB *= -1;
- btVector3 nB = swapFactor * computedNormalB;
-
-#ifdef DEBUG_INTERNAL_EDGE
- {
- btDebugDrawLine(cp.getPositionWorldOnB(), cp.getPositionWorldOnB() + tr.getBasis() * (nB * 20), red);
- }
-#endif //DEBUG_INTERNAL_EDGE
-
- btScalar NdotA = localContactNormalOnB.dot(nA);
- btScalar NdotB = localContactNormalOnB.dot(nB);
- bool backFacingNormal = (NdotA < triangleInfoMapPtr->m_convexEpsilon) && (NdotB < triangleInfoMapPtr->m_convexEpsilon);
-
- if (backFacingNormal)
- {
- numConcaveEdgeHits++;
- }
- else
- {
- numConvexEdgeHits++;
- btVector3 localContactNormalOnB = colObj0Wrap->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB;
- btVector3 clampedLocalNormal;
- bool isClamped = btClampNormal(edge, swapFactor * tri_normal, localContactNormalOnB, info->m_edgeV1V2Angle, clampedLocalNormal);
- if (isClamped)
- {
- if (((normalAdjustFlags & BT_TRIANGLE_CONVEX_DOUBLE_SIDED) != 0) || (clampedLocalNormal.dot(frontFacing * tri_normal) > 0))
- {
- btVector3 newNormal = colObj0Wrap->getWorldTransform().getBasis() * clampedLocalNormal;
- // cp.m_distance1 = cp.m_distance1 * newNormal.dot(cp.m_normalWorldOnB);
- cp.m_normalWorldOnB = newNormal;
- // Reproject collision point along normal.
- cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
- cp.m_localPointB = colObj0Wrap->getWorldTransform().invXform(cp.m_positionWorldOnB);
- }
- }
- }
- }
- }
- }
-
- btNearestPointInLineSegment(contact, v2, v0, nearest);
-#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
- btDebugDrawLine(tr * nearest, tr * cp.m_localPointB, blue);
-#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
-#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
- btDebugDrawLine(tr * v2 + upfix, tr * v0 + upfix, blue);
-#endif
-
- if (btFabs(info->m_edgeV2V0Angle) < triangleInfoMapPtr->m_maxEdgeAngleThreshold)
- {
-#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
- btDebugDrawLine(tr * contact, tr * (contact + cp.m_normalWorldOnB * 10), black);
-#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
-
- btScalar len = (contact - nearest).length();
- if (len < triangleInfoMapPtr->m_edgeDistanceThreshold)
- if (bestedge == 2)
- {
- isNearEdge = true;
-#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
- btDebugDrawLine(tr * nearest, tr * (nearest + tri_normal * 10), white);
-#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
-
- btVector3 edge(v2 - v0);
-
- if (info->m_edgeV2V0Angle == btScalar(0))
- {
- numConcaveEdgeHits++;
- }
- else
- {
- bool isEdgeConvex = (info->m_flags & TRI_INFO_V2V0_CONVEX) != 0;
- btScalar swapFactor = isEdgeConvex ? btScalar(1) : btScalar(-1);
-#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
- btDebugDrawLine(tr * nearest, tr * (nearest + swapFactor * tri_normal * 10), white);
-#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
-
- btVector3 nA = swapFactor * tri_normal;
- btQuaternion orn(edge, info->m_edgeV2V0Angle);
- btVector3 computedNormalB = quatRotate(orn, tri_normal);
- if (info->m_flags & TRI_INFO_V2V0_SWAP_NORMALB)
- computedNormalB *= -1;
- btVector3 nB = swapFactor * computedNormalB;
-
-#ifdef DEBUG_INTERNAL_EDGE
- {
- btDebugDrawLine(cp.getPositionWorldOnB(), cp.getPositionWorldOnB() + tr.getBasis() * (nB * 20), red);
- }
-#endif //DEBUG_INTERNAL_EDGE
-
- btScalar NdotA = localContactNormalOnB.dot(nA);
- btScalar NdotB = localContactNormalOnB.dot(nB);
- bool backFacingNormal = (NdotA < triangleInfoMapPtr->m_convexEpsilon) && (NdotB < triangleInfoMapPtr->m_convexEpsilon);
-
- if (backFacingNormal)
- {
- numConcaveEdgeHits++;
- }
- else
- {
- numConvexEdgeHits++;
- // printf("hitting convex edge\n");
-
- btVector3 localContactNormalOnB = colObj0Wrap->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB;
- btVector3 clampedLocalNormal;
- bool isClamped = btClampNormal(edge, swapFactor * tri_normal, localContactNormalOnB, info->m_edgeV2V0Angle, clampedLocalNormal);
- if (isClamped)
- {
- if (((normalAdjustFlags & BT_TRIANGLE_CONVEX_DOUBLE_SIDED) != 0) || (clampedLocalNormal.dot(frontFacing * tri_normal) > 0))
- {
- btVector3 newNormal = colObj0Wrap->getWorldTransform().getBasis() * clampedLocalNormal;
- // cp.m_distance1 = cp.m_distance1 * newNormal.dot(cp.m_normalWorldOnB);
- cp.m_normalWorldOnB = newNormal;
- // Reproject collision point along normal.
- cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
- cp.m_localPointB = colObj0Wrap->getWorldTransform().invXform(cp.m_positionWorldOnB);
- }
- }
- }
- }
- }
- }
-
-#ifdef DEBUG_INTERNAL_EDGE
- {
- btVector3 color(0, 1, 1);
- btDebugDrawLine(cp.getPositionWorldOnB(), cp.getPositionWorldOnB() + cp.m_normalWorldOnB * 10, color);
- }
-#endif //DEBUG_INTERNAL_EDGE
-
- if (isNearEdge)
- {
- if (numConcaveEdgeHits > 0)
- {
- if ((normalAdjustFlags & BT_TRIANGLE_CONCAVE_DOUBLE_SIDED) != 0)
- {
- //fix tri_normal so it pointing the same direction as the current local contact normal
- if (tri_normal.dot(localContactNormalOnB) < 0)
- {
- tri_normal *= -1;
- }
- cp.m_normalWorldOnB = colObj0Wrap->getWorldTransform().getBasis() * tri_normal;
- }
- else
- {
- btVector3 newNormal = tri_normal * frontFacing;
- //if the tri_normal is pointing opposite direction as the current local contact normal, skip it
- btScalar d = newNormal.dot(localContactNormalOnB);
- if (d < 0)
- {
- return;
- }
- //modify the normal to be the triangle normal (or backfacing normal)
- cp.m_normalWorldOnB = colObj0Wrap->getWorldTransform().getBasis() * newNormal;
- }
-
- // Reproject collision point along normal.
- cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
- cp.m_localPointB = colObj0Wrap->getWorldTransform().invXform(cp.m_positionWorldOnB);
- }
- }
-}