1 #include "btInternalEdgeUtility.h"
2 
3 #include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
4 #include "BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h"
5 
6 #include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h"
7 #include "BulletCollision/CollisionShapes/btTriangleShape.h"
8 #include "BulletCollision/CollisionDispatch/btCollisionObject.h"
9 #include "BulletCollision/NarrowPhaseCollision/btManifoldPoint.h"
10 #include "LinearMath/btIDebugDraw.h"
11 #include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
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 
btSetDebugDrawer(btIDebugDraw * debugDrawer)22 void btSetDebugDrawer(btIDebugDraw* debugDrawer)
23 {
24 	gDebugDrawer = debugDrawer;
25 }
26 
btDebugDrawLine(const btVector3 & from,const btVector3 & to,const btVector3 & color)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 
btGetHash(int partId,int triangleIndex)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 
btGetAngle(const btVector3 & edgeA,const btVector3 & normalA,const btVector3 & normalB)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 
49 struct btConnectivityProcessor : public btTriangleCallback
50 {
51 	int m_partIdA;
52 	int m_triangleIndexA;
53 	btVector3* m_triangleVerticesA;
54 	btTriangleInfoMap* m_triangleInfoMap;
55 
processTrianglebtConnectivityProcessor56 	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 
71 		///skip degenerate triangles
72 		btScalar crossBSqr = ((triangle[1] - triangle[0]).cross(triangle[2] - triangle[0])).length2();
73 		if (crossBSqr < m_triangleInfoMap->m_equalVertexThreshold)
74 			return;
75 
76 		btScalar crossASqr = ((m_triangleVerticesA[1] - m_triangleVerticesA[0]).cross(m_triangleVerticesA[2] - m_triangleVerticesA[0])).length2();
77 		///skip degenerate triangles
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",
83 			m_triangleVerticesA[0].getX(),m_triangleVerticesA[0].getY(),m_triangleVerticesA[0].getZ(),
84 			m_triangleVerticesA[1].getX(),m_triangleVerticesA[1].getY(),m_triangleVerticesA[1].getZ(),
85 			m_triangleVerticesA[2].getX(),m_triangleVerticesA[2].getY(),m_triangleVerticesA[2].getZ());
86 
87 		printf("partId=%d, triangleIndex=%d\n",partId,triangleIndex);
88 		printf("triangle B[0]	=	(%f,%f,%f)\ntriangle B[1]	=	(%f,%f,%f)\ntriangle B[2]	=	(%f,%f,%f)\n",
89 			triangle[0].getX(),triangle[0].getY(),triangle[0].getZ(),
90 			triangle[1].getX(),triangle[1].getY(),triangle[1].getZ(),
91 			triangle[2].getX(),triangle[2].getY(),triangle[2].getZ());
92 #endif
93 
94 		for (int i = 0; i < 3; i++)
95 		{
96 			for (int j = 0; j < 3; j++)
97 			{
98 				if ((m_triangleVerticesA[i] - triangle[j]).length2() < m_triangleInfoMap->m_equalVertexThreshold)
99 				{
100 					sharedVertsA[numshared] = i;
101 					sharedVertsB[numshared] = j;
102 					numshared++;
103 					///degenerate case
104 					if (numshared >= 3)
105 						return;
106 				}
107 			}
108 			///degenerate case
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 
136 				int hash = btGetHash(m_partIdA, m_triangleIndexA);
137 
138 				btTriangleInfo* info = m_triangleInfoMap->find(hash);
139 				if (!info)
140 				{
141 					btTriangleInfo tmp;
142 					m_triangleInfoMap->insert(hash, 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);
205 					///@todo: check if we need some epsilon, due to floating point imprecision
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;
225 							info->m_flags |= TRI_INFO_V0V1_SWAP_NORMALB;
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 					{
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;
248 							info->m_flags |= TRI_INFO_V2V0_SWAP_NORMALB;
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 					{
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 						{
269 							info->m_flags |= TRI_INFO_V1V2_SWAP_NORMALB;
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 
297 struct b3ProcessAllTrianglesHeightfield: public btTriangleCallback
298 {
299 	btHeightfieldTerrainShape* m_heightfieldShape;
300 	btTriangleInfoMap* m_triangleInfoMap;
301 
302 
b3ProcessAllTrianglesHeightfieldb3ProcessAllTrianglesHeightfield303 	b3ProcessAllTrianglesHeightfield(btHeightfieldTerrainShape* heightFieldShape, btTriangleInfoMap* triangleInfoMap)
304 		:m_heightfieldShape(heightFieldShape),
305 		m_triangleInfoMap(triangleInfoMap)
306 	{
307 	}
processTriangleb3ProcessAllTrianglesHeightfield308 	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;
316 		aabbMin.setValue(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
317 		aabbMax.setValue(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
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 };
328 /////////////////////////////////////////////////////////
329 /////////////////////////////////////////////////////////
330 
btGenerateInternalEdgeInfo(btBvhTriangleMeshShape * trimeshShape,btTriangleInfoMap * triangleInfoMap)331 void btGenerateInternalEdgeInfo(btBvhTriangleMeshShape* trimeshShape, btTriangleInfoMap* triangleInfoMap)
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;
346 		PHY_ScalarType type = PHY_INTEGER;
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 			}
385 			aabbMin.setValue(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
386 			aabbMax.setValue(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
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 
btGenerateInternalEdgeInfo(btHeightfieldTerrainShape * heightfieldShape,btTriangleInfoMap * triangleInfoMap)406 void btGenerateInternalEdgeInfo(btHeightfieldTerrainShape* heightfieldShape, btTriangleInfoMap* triangleInfoMap)
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 
419 	aabbMax.setValue(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
420 	aabbMin.setValue(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
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.
btNearestPointInLineSegment(const btVector3 & point,const btVector3 & line0,const btVector3 & line1,btVector3 & nearestPoint)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 
btClampNormal(const btVector3 & edge,const btVector3 & tri_normal_org,const btVector3 & localContactNormalOnB,btScalar correctedEdgeAngle,btVector3 & clampedLocalNormal)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 
485 /// Changes a btManifoldPoint collision normal to the normal from the mesh.
btAdjustInternalEdgeContacts(btManifoldPoint & cp,const btCollisionObjectWrapper * colObj0Wrap,const btCollisionObjectWrapper * colObj1Wrap,int partId0,int index0,int normalAdjustFlags)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?)
511 		cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
512 		cp.m_localPointB = colObj0Wrap->getWorldTransform().invXform(cp.m_positionWorldOnB);
513 		return;
514 #endif
515 	}
516 
517 
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;
599 		btNearestPointInLineSegment(cp.m_localPointB, v1, v2, nearest);
600 		btScalar len = (contact - nearest).length();
601 		//
602 		if (len < disttobestedge)
603 		{
604 			bestedge = 1;
605 			disttobestedge = len;
606 		}
607 	}
608 	// Edge 2 -> 0
609 	if (btFabs(info->m_edgeV2V0Angle) < triangleInfoMapPtr->m_maxEdgeAngleThreshold)
610 	{
611 		btVector3 nearest;
612 		btNearestPointInLineSegment(cp.m_localPointB, v2, v0, nearest);
613 		btScalar len = (contact - nearest).length();
614 		//
615 		if (len < disttobestedge)
616 		{
617 			bestedge = 2;
618 			disttobestedge = len;
619 		}
620 	}
621 
622 #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
623 	btVector3 upfix = tri_normal * btVector3(0.1f, 0.1f, 0.1f);
624 	btDebugDrawLine(tr * v0 + upfix, tr * v1 + upfix, red);
625 #endif
626 	if (btFabs(info->m_edgeV0V1Angle) < triangleInfoMapPtr->m_maxEdgeAngleThreshold)
627 	{
628 #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
629 		btDebugDrawLine(tr * contact, tr * (contact + cp.m_normalWorldOnB * 10), black);
630 #endif
631 		btScalar len = (contact - nearest).length();
632 		if (len < triangleInfoMapPtr->m_edgeDistanceThreshold)
633 			if (bestedge == 0)
634 			{
635 				btVector3 edge(v0 - v1);
636 				isNearEdge = true;
637 
638 				if (info->m_edgeV0V1Angle == btScalar(0))
639 				{
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);
654 					if (info->m_flags & TRI_INFO_V0V1_SWAP_NORMALB)
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?)
685 								cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
686 								cp.m_localPointB = colObj0Wrap->getWorldTransform().invXform(cp.m_positionWorldOnB);
687 							}
688 						}
689 					}
690 				}
691 			}
692 	}
693 
694 	btNearestPointInLineSegment(contact, v1, v2, nearest);
695 #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
696 	btDebugDrawLine(tr * nearest, tr * cp.m_localPointB, green);
697 #endif  //BT_INTERNAL_EDGE_DEBUG_DRAW
698 
699 #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
700 	btDebugDrawLine(tr * v1 + upfix, tr * v2 + upfix, green);
701 #endif
702 
703 	if (btFabs(info->m_edgeV1V2Angle) < triangleInfoMapPtr->m_maxEdgeAngleThreshold)
704 	{
705 #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
706 		btDebugDrawLine(tr * contact, tr * (contact + cp.m_normalWorldOnB * 10), black);
707 #endif  //BT_INTERNAL_EDGE_DEBUG_DRAW
708 
709 		btScalar len = (contact - nearest).length();
710 		if (len < triangleInfoMapPtr->m_edgeDistanceThreshold)
711 			if (bestedge == 1)
712 			{
713 				isNearEdge = true;
714 #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
715 				btDebugDrawLine(tr * nearest, tr * (nearest + tri_normal * 10), white);
716 #endif  //BT_INTERNAL_EDGE_DEBUG_DRAW
717 
718 				btVector3 edge(v1 - v2);
719 
720 				isNearEdge = true;
721 
722 				if (info->m_edgeV1V2Angle == btScalar(0))
723 				{
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);
738 					if (info->m_flags & TRI_INFO_V1V2_SWAP_NORMALB)
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.
770 								cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
771 								cp.m_localPointB = colObj0Wrap->getWorldTransform().invXform(cp.m_positionWorldOnB);
772 							}
773 						}
774 					}
775 				}
776 			}
777 	}
778 
779 	btNearestPointInLineSegment(contact, v2, v0, nearest);
780 #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
781 	btDebugDrawLine(tr * nearest, tr * cp.m_localPointB, blue);
782 #endif  //BT_INTERNAL_EDGE_DEBUG_DRAW
783 #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
784 	btDebugDrawLine(tr * v2 + upfix, tr * v0 + upfix, blue);
785 #endif
786 
787 	if (btFabs(info->m_edgeV2V0Angle) < triangleInfoMapPtr->m_maxEdgeAngleThreshold)
788 	{
789 #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
790 		btDebugDrawLine(tr * contact, tr * (contact + cp.m_normalWorldOnB * 10), black);
791 #endif  //BT_INTERNAL_EDGE_DEBUG_DRAW
792 
793 		btScalar len = (contact - nearest).length();
794 		if (len < triangleInfoMapPtr->m_edgeDistanceThreshold)
795 			if (bestedge == 2)
796 			{
797 				isNearEdge = true;
798 #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
799 				btDebugDrawLine(tr * nearest, tr * (nearest + tri_normal * 10), white);
800 #endif  //BT_INTERNAL_EDGE_DEBUG_DRAW
801 
802 				btVector3 edge(v2 - v0);
803 
804 				if (info->m_edgeV2V0Angle == btScalar(0))
805 				{
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);
819 					if (info->m_flags & TRI_INFO_V2V0_SWAP_NORMALB)
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.
853 								cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
854 								cp.m_localPointB = colObj0Wrap->getWorldTransform().invXform(cp.m_positionWorldOnB);
855 							}
856 						}
857 					}
858 				}
859 			}
860 	}
861 
862 #ifdef DEBUG_INTERNAL_EDGE
863 	{
864 		btVector3 color(0, 1, 1);
865 		btDebugDrawLine(cp.getPositionWorldOnB(), cp.getPositionWorldOnB() + cp.m_normalWorldOnB * 10, color);
866 	}
867 #endif  //DEBUG_INTERNAL_EDGE
868 
869 	if (isNearEdge)
870 	{
871 		if (numConcaveEdgeHits > 0)
872 		{
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.
896 			cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
897 			cp.m_localPointB = colObj0Wrap->getWorldTransform().invXform(cp.m_positionWorldOnB);
898 		}
899 	}
900 }
901