mpr.cl 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. #include "Bullet3Collision/NarrowPhaseCollision/shared/b3MprPenetration.h"
  2. #include "Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h"
  3. #define AppendInc(x, out) out = atomic_inc(x)
  4. #define GET_NPOINTS(x) (x).m_worldNormalOnB.w
  5. #ifdef cl_ext_atomic_counters_32
  6. #pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable
  7. #else
  8. #define counter32_t volatile __global int*
  9. #endif
  10. __kernel void mprPenetrationKernel( __global int4* pairs,
  11. __global const b3RigidBodyData_t* rigidBodies,
  12. __global const b3Collidable_t* collidables,
  13. __global const b3ConvexPolyhedronData_t* convexShapes,
  14. __global const float4* vertices,
  15. __global float4* separatingNormals,
  16. __global int* hasSeparatingAxis,
  17. __global struct b3Contact4Data* restrict globalContactsOut,
  18. counter32_t nGlobalContactsOut,
  19. int contactCapacity,
  20. int numPairs)
  21. {
  22. int i = get_global_id(0);
  23. int pairIndex = i;
  24. if (i<numPairs)
  25. {
  26. int bodyIndexA = pairs[i].x;
  27. int bodyIndexB = pairs[i].y;
  28. int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
  29. int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
  30. int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
  31. int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
  32. //once the broadphase avoids static-static pairs, we can remove this test
  33. if ((rigidBodies[bodyIndexA].m_invMass==0) &&(rigidBodies[bodyIndexB].m_invMass==0))
  34. {
  35. return;
  36. }
  37. if ((collidables[collidableIndexA].m_shapeType!=SHAPE_CONVEX_HULL) ||(collidables[collidableIndexB].m_shapeType!=SHAPE_CONVEX_HULL))
  38. {
  39. return;
  40. }
  41. float depthOut;
  42. b3Float4 dirOut;
  43. b3Float4 posOut;
  44. int res = b3MprPenetration(pairIndex, bodyIndexA, bodyIndexB,rigidBodies,convexShapes,collidables,vertices,separatingNormals,hasSeparatingAxis,&depthOut, &dirOut, &posOut);
  45. if (res==0)
  46. {
  47. //add a contact
  48. int dstIdx;
  49. AppendInc( nGlobalContactsOut, dstIdx );
  50. if (dstIdx<contactCapacity)
  51. {
  52. pairs[pairIndex].z = dstIdx;
  53. __global struct b3Contact4Data* c = globalContactsOut + dstIdx;
  54. c->m_worldNormalOnB = -dirOut;//normal;
  55. c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);
  56. c->m_batchIdx = pairIndex;
  57. int bodyA = pairs[pairIndex].x;
  58. int bodyB = pairs[pairIndex].y;
  59. c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0 ? -bodyA:bodyA;
  60. c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0 ? -bodyB:bodyB;
  61. c->m_childIndexA = -1;
  62. c->m_childIndexB = -1;
  63. //for (int i=0;i<nContacts;i++)
  64. posOut.w = -depthOut;
  65. c->m_worldPosB[0] = posOut;//localPoints[contactIdx[i]];
  66. GET_NPOINTS(*c) = 1;//nContacts;
  67. }
  68. }
  69. }
  70. }
  71. typedef float4 Quaternion;
  72. #define make_float4 (float4)
  73. __inline
  74. float dot3F4(float4 a, float4 b)
  75. {
  76. float4 a1 = make_float4(a.xyz,0.f);
  77. float4 b1 = make_float4(b.xyz,0.f);
  78. return dot(a1, b1);
  79. }
  80. __inline
  81. float4 cross3(float4 a, float4 b)
  82. {
  83. return cross(a,b);
  84. }
  85. __inline
  86. Quaternion qtMul(Quaternion a, Quaternion b)
  87. {
  88. Quaternion ans;
  89. ans = cross3( a, b );
  90. ans += a.w*b+b.w*a;
  91. // ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);
  92. ans.w = a.w*b.w - dot3F4(a, b);
  93. return ans;
  94. }
  95. __inline
  96. Quaternion qtInvert(Quaternion q)
  97. {
  98. return (Quaternion)(-q.xyz, q.w);
  99. }
  100. __inline
  101. float4 qtRotate(Quaternion q, float4 vec)
  102. {
  103. Quaternion qInv = qtInvert( q );
  104. float4 vcpy = vec;
  105. vcpy.w = 0.f;
  106. float4 out = qtMul(qtMul(q,vcpy),qInv);
  107. return out;
  108. }
  109. __inline
  110. float4 transform(const float4* p, const float4* translation, const Quaternion* orientation)
  111. {
  112. return qtRotate( *orientation, *p ) + (*translation);
  113. }
  114. __inline
  115. float4 qtInvRotate(const Quaternion q, float4 vec)
  116. {
  117. return qtRotate( qtInvert( q ), vec );
  118. }
  119. inline void project(__global const b3ConvexPolyhedronData_t* hull, const float4 pos, const float4 orn,
  120. const float4* dir, __global const float4* vertices, float* min, float* max)
  121. {
  122. min[0] = FLT_MAX;
  123. max[0] = -FLT_MAX;
  124. int numVerts = hull->m_numVertices;
  125. const float4 localDir = qtInvRotate(orn,*dir);
  126. float offset = dot(pos,*dir);
  127. for(int i=0;i<numVerts;i++)
  128. {
  129. float dp = dot(vertices[hull->m_vertexOffset+i],localDir);
  130. if(dp < min[0])
  131. min[0] = dp;
  132. if(dp > max[0])
  133. max[0] = dp;
  134. }
  135. if(min[0]>max[0])
  136. {
  137. float tmp = min[0];
  138. min[0] = max[0];
  139. max[0] = tmp;
  140. }
  141. min[0] += offset;
  142. max[0] += offset;
  143. }
  144. bool findSeparatingAxisUnitSphere( __global const b3ConvexPolyhedronData_t* hullA, __global const b3ConvexPolyhedronData_t* hullB,
  145. const float4 posA1,
  146. const float4 ornA,
  147. const float4 posB1,
  148. const float4 ornB,
  149. const float4 DeltaC2,
  150. __global const float4* vertices,
  151. __global const float4* unitSphereDirections,
  152. int numUnitSphereDirections,
  153. float4* sep,
  154. float* dmin)
  155. {
  156. float4 posA = posA1;
  157. posA.w = 0.f;
  158. float4 posB = posB1;
  159. posB.w = 0.f;
  160. int curPlaneTests=0;
  161. int curEdgeEdge = 0;
  162. // Test unit sphere directions
  163. for (int i=0;i<numUnitSphereDirections;i++)
  164. {
  165. float4 crossje;
  166. crossje = unitSphereDirections[i];
  167. if (dot3F4(DeltaC2,crossje)>0)
  168. crossje *= -1.f;
  169. {
  170. float dist;
  171. bool result = true;
  172. float Min0,Max0;
  173. float Min1,Max1;
  174. project(hullA,posA,ornA,&crossje,vertices, &Min0, &Max0);
  175. project(hullB,posB,ornB,&crossje,vertices, &Min1, &Max1);
  176. if(Max0<Min1 || Max1<Min0)
  177. return false;
  178. float d0 = Max0 - Min1;
  179. float d1 = Max1 - Min0;
  180. dist = d0<d1 ? d0:d1;
  181. result = true;
  182. if(dist<*dmin)
  183. {
  184. *dmin = dist;
  185. *sep = crossje;
  186. }
  187. }
  188. }
  189. if((dot3F4(-DeltaC2,*sep))>0.0f)
  190. {
  191. *sep = -(*sep);
  192. }
  193. return true;
  194. }
  195. __kernel void findSeparatingAxisUnitSphereKernel( __global const int4* pairs,
  196. __global const b3RigidBodyData_t* rigidBodies,
  197. __global const b3Collidable_t* collidables,
  198. __global const b3ConvexPolyhedronData_t* convexShapes,
  199. __global const float4* vertices,
  200. __global const float4* unitSphereDirections,
  201. __global float4* separatingNormals,
  202. __global int* hasSeparatingAxis,
  203. __global float* dmins,
  204. int numUnitSphereDirections,
  205. int numPairs
  206. )
  207. {
  208. int i = get_global_id(0);
  209. if (i<numPairs)
  210. {
  211. if (hasSeparatingAxis[i])
  212. {
  213. int bodyIndexA = pairs[i].x;
  214. int bodyIndexB = pairs[i].y;
  215. int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
  216. int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
  217. int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
  218. int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
  219. int numFacesA = convexShapes[shapeIndexA].m_numFaces;
  220. float dmin = dmins[i];
  221. float4 posA = rigidBodies[bodyIndexA].m_pos;
  222. posA.w = 0.f;
  223. float4 posB = rigidBodies[bodyIndexB].m_pos;
  224. posB.w = 0.f;
  225. float4 c0local = convexShapes[shapeIndexA].m_localCenter;
  226. float4 ornA = rigidBodies[bodyIndexA].m_quat;
  227. float4 c0 = transform(&c0local, &posA, &ornA);
  228. float4 c1local = convexShapes[shapeIndexB].m_localCenter;
  229. float4 ornB =rigidBodies[bodyIndexB].m_quat;
  230. float4 c1 = transform(&c1local,&posB,&ornB);
  231. const float4 DeltaC2 = c0 - c1;
  232. float4 sepNormal = separatingNormals[i];
  233. int numEdgeEdgeDirections = convexShapes[shapeIndexA].m_numUniqueEdges*convexShapes[shapeIndexB].m_numUniqueEdges;
  234. if (numEdgeEdgeDirections>numUnitSphereDirections)
  235. {
  236. bool sepEE = findSeparatingAxisUnitSphere( &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,
  237. posB,ornB,
  238. DeltaC2,
  239. vertices,unitSphereDirections,numUnitSphereDirections,&sepNormal,&dmin);
  240. if (!sepEE)
  241. {
  242. hasSeparatingAxis[i] = 0;
  243. } else
  244. {
  245. hasSeparatingAxis[i] = 1;
  246. separatingNormals[i] = sepNormal;
  247. }
  248. }
  249. } //if (hasSeparatingAxis[i])
  250. }//(i<numPairs)
  251. }