GpuConvexScene.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651
  1. #include "GpuConvexScene.h"
  2. #include "GpuRigidBodyDemo.h"
  3. #include "../OpenGLWindow/ShapeData.h"
  4. #include "../OpenGLWindow/GLInstancingRenderer.h"
  5. #include "Bullet3Common/b3Quaternion.h"
  6. #include "../CommonInterfaces/CommonWindowInterface.h"
  7. #include "Bullet3OpenCL/BroadphaseCollision/b3GpuSapBroadphase.h"
  8. #include "../CommonOpenCL/GpuDemoInternalData.h"
  9. #include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
  10. #include "../OpenGLWindow/OpenGLInclude.h"
  11. #include "../OpenGLWindow/GLInstanceRendererInternalData.h"
  12. #include "Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h"
  13. #include "Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipeline.h"
  14. #include "Bullet3OpenCL/RigidBody/b3GpuNarrowPhase.h"
  15. #include "Bullet3Collision/NarrowPhaseCollision/b3Config.h"
  16. #include "GpuRigidBodyDemoInternalData.h"
  17. #include "Bullet3Dynamics/ConstraintSolver/b3Point2PointConstraint.h"
  18. #include "../OpenGLWindow/GLPrimitiveRenderer.h"
  19. #include "Bullet3OpenCL/Raycast/b3GpuRaycast.h"
  20. #include "Bullet3Collision/NarrowPhaseCollision/b3ConvexUtility.h"
  21. #include "Bullet3Dynamics/ConstraintSolver/b3FixedConstraint.h"
  22. #include "../OpenGLWindow/GLRenderToTexture.h"
  23. static bool gUseInstancedCollisionShapes = true;
  24. extern int gGpuArraySizeX;
  25. extern int gGpuArraySizeY;
  26. extern int gGpuArraySizeZ;
  27. #include "GpuRigidBodyDemo.h"
  28. #include "Bullet3Common/b3AlignedObjectArray.h"
  29. #include "Bullet3Collision/NarrowPhaseCollision/b3RaycastInfo.h"
  30. class GpuConvexScene : public GpuRigidBodyDemo
  31. {
  32. protected:
  33. class b3GpuRaycast* m_raycaster;
  34. public:
  35. GpuConvexScene(GUIHelperInterface* helper)
  36. :GpuRigidBodyDemo(helper), m_raycaster(0)
  37. {
  38. }
  39. virtual ~GpuConvexScene(){}
  40. virtual const char* getName()
  41. {
  42. return "Tetrahedra";
  43. }
  44. virtual void setupScene();
  45. virtual void destroyScene();
  46. virtual int createDynamicsObjects();
  47. virtual int createDynamicsObjects2(const float* vertices, int numVertices, const int* indices,int numIndices);
  48. virtual void createStaticEnvironment();
  49. };
  50. class GpuConvexPlaneScene : public GpuConvexScene
  51. {
  52. public:
  53. GpuConvexPlaneScene(GUIHelperInterface* helper)
  54. :GpuConvexScene(helper){}
  55. virtual ~GpuConvexPlaneScene(){}
  56. virtual const char* getName()
  57. {
  58. return "ConvexOnPlane";
  59. }
  60. virtual void createStaticEnvironment();
  61. };
  62. class GpuBoxPlaneScene : public GpuConvexPlaneScene
  63. {
  64. public:
  65. GpuBoxPlaneScene(GUIHelperInterface* helper):GpuConvexPlaneScene(helper){}
  66. virtual ~GpuBoxPlaneScene(){}
  67. virtual const char* getName()
  68. {
  69. return "BoxBox";
  70. }
  71. virtual int createDynamicsObjects();
  72. };
  73. class GpuTetraScene : public GpuConvexScene
  74. {
  75. protected:
  76. void createFromTetGenData(const char* ele, const char* node);
  77. public:
  78. virtual const char* getName()
  79. {
  80. return "TetraBreakable";
  81. }
  82. virtual int createDynamicsObjects();
  83. };
  84. b3Vector4 colors[4] =
  85. {
  86. b3MakeVector4(1,0,0,1),
  87. b3MakeVector4(0,1,0,1),
  88. b3MakeVector4(0,1,1,1),
  89. b3MakeVector4(1,1,0,1),
  90. };
  91. void GpuConvexScene::setupScene()
  92. {
  93. m_raycaster = new b3GpuRaycast(m_clData->m_clContext,m_clData->m_clDevice,m_clData->m_clQueue);
  94. int index=0;
  95. createStaticEnvironment();
  96. index+=createDynamicsObjects();
  97. m_data->m_rigidBodyPipeline->writeAllInstancesToGpu();
  98. float camPos[4]={0,0,0,0};//ci.arraySizeX,ci.arraySizeY/2,ci.arraySizeZ,0};
  99. //float camPos[4]={1,12.5,1.5,0};
  100. m_guiHelper->getRenderInterface()->getActiveCamera()->setCameraTargetPosition(camPos[0],camPos[1],camPos[2]);
  101. m_guiHelper->getRenderInterface()->getActiveCamera()->setCameraDistance(150);
  102. //m_instancingRenderer->setCameraYaw(85);
  103. m_guiHelper->getRenderInterface()->getActiveCamera()->setCameraYaw(30);
  104. m_guiHelper->getRenderInterface()->getActiveCamera()->setCameraPitch(225);
  105. m_guiHelper->getRenderInterface()->updateCamera(1);//>updateCamera();
  106. char msg[1024];
  107. int numInstances = index;
  108. sprintf(msg,"Num objects = %d",numInstances);
  109. b3Printf(msg);
  110. //if (ci.m_gui)
  111. // ci.m_gui->setStatusBarMessage(msg,true);
  112. }
  113. void GpuConvexScene::destroyScene()
  114. {
  115. delete m_raycaster;
  116. m_raycaster = 0;
  117. }
  118. int GpuConvexScene::createDynamicsObjects()
  119. {
  120. int strideInBytes = 9*sizeof(float);
  121. /*int numVertices = sizeof(barrel_vertices)/strideInBytes;
  122. int numIndices = sizeof(barrel_indices)/sizeof(int);
  123. return createDynamicsObjects2(ci,barrel_vertices,numVertices,barrel_indices,numIndices);
  124. */
  125. int numVertices = sizeof(tetra_vertices)/strideInBytes;
  126. int numIndices = sizeof(tetra_indices)/sizeof(int);
  127. return createDynamicsObjects2(tetra_vertices,numVertices,tetra_indices,numIndices);
  128. }
  129. int GpuBoxPlaneScene::createDynamicsObjects()
  130. {
  131. int strideInBytes = 9*sizeof(float);
  132. int numVertices = sizeof(cube_vertices)/strideInBytes;
  133. int numIndices = sizeof(cube_indices)/sizeof(int);
  134. return createDynamicsObjects2(cube_vertices_textured,numVertices,cube_indices,numIndices);
  135. }
  136. int GpuConvexScene::createDynamicsObjects2( const float* vertices, int numVertices, const int* indices, int numIndices)
  137. {
  138. int strideInBytes = 9*sizeof(float);
  139. int textureIndex = -1;
  140. if (0)
  141. {
  142. int width,height,n;
  143. const char* filename = "data/cube.png";
  144. const unsigned char* image=0;
  145. const char* prefix[]={"./","../","../../","../../../","../../../../"};
  146. int numprefix = sizeof(prefix)/sizeof(const char*);
  147. for (int i=0;!image && i<numprefix;i++)
  148. {
  149. char relativeFileName[1024];
  150. sprintf(relativeFileName,"%s%s",prefix[i],filename);
  151. image = loadImage(relativeFileName,width,height,n);
  152. }
  153. b3Assert(image);
  154. if (image)
  155. {
  156. textureIndex = m_instancingRenderer->registerTexture(image,width,height);
  157. }
  158. }
  159. int shapeId = m_guiHelper->getRenderInterface()->registerShape(&vertices[0],numVertices,indices,numIndices,B3_GL_TRIANGLES,textureIndex);
  160. int group=1;
  161. int mask=1;
  162. int index=0;
  163. {
  164. int curColor = 0;
  165. float scaling[4] = {1,1,1,1};
  166. int prevBody = -1;
  167. int insta = 0;
  168. b3ConvexUtility* utilPtr = new b3ConvexUtility();
  169. {
  170. b3AlignedObjectArray<b3Vector3> verts;
  171. unsigned char* vts = (unsigned char*) vertices;
  172. for (int i=0;i<numVertices;i++)
  173. {
  174. float* vertex = (float*) &vts[i*strideInBytes];
  175. verts.push_back(b3MakeVector3(vertex[0]*scaling[0],vertex[1]*scaling[1],vertex[2]*scaling[2]));
  176. }
  177. bool merge = true;
  178. if (numVertices)
  179. {
  180. utilPtr->initializePolyhedralFeatures(&verts[0],verts.size(),merge);
  181. }
  182. }
  183. int colIndex=-1;
  184. if (gUseInstancedCollisionShapes)
  185. colIndex = m_data->m_np->registerConvexHullShape(utilPtr);
  186. //int colIndex = m_data->m_np->registerSphereShape(1);
  187. for (int i=0;i<gGpuArraySizeX;i++)
  188. {
  189. //printf("%d of %d\n", i, ci.arraySizeX);
  190. for (int j=0;j<gGpuArraySizeY;j++)
  191. {
  192. for (int k=0;k<gGpuArraySizeZ;k++)
  193. {
  194. //int colIndex = m_data->m_np->registerConvexHullShape(&vertices[0],strideInBytes,numVertices, scaling);
  195. if (!gUseInstancedCollisionShapes)
  196. colIndex = m_data->m_np->registerConvexHullShape(utilPtr);
  197. float mass = 1.f;
  198. if (j==0)//ci.arraySizeY-1)
  199. {
  200. //mass=0.f;
  201. }
  202. b3Vector3 position = b3MakeVector3(((j+1)&1)+i*2.2,1+j*2.,((j+1)&1)+k*2.2);
  203. //b3Vector3 position = b3MakeVector3(i*2,1+j*2,k*2);
  204. //b3Vector3 position=b3MakeVector3(1,0.9,1);
  205. b3Quaternion orn(0,0,0,1);
  206. b3Vector4 color = colors[curColor];
  207. curColor++;
  208. curColor&=3;
  209. b3Vector4 scalin=b3MakeVector4(1,1,1,1);
  210. int id = m_guiHelper->getRenderInterface()->registerGraphicsInstance(shapeId,position,orn,color,scaling);
  211. int pid = m_data->m_rigidBodyPipeline->registerPhysicsInstance(mass,position,orn,colIndex,index,false);
  212. if (prevBody>=0)
  213. {
  214. //b3Point2PointConstraint* p2p = new b3Point2PointConstraint(pid,prevBody,b3Vector3(0,-1.1,0),b3Vector3(0,1.1,0));
  215. // m_data->m_rigidBodyPipeline->addConstraint(p2p);//,false);
  216. }
  217. prevBody = pid;
  218. index++;
  219. }
  220. }
  221. }
  222. delete utilPtr;
  223. }
  224. return index;
  225. }
  226. void GpuConvexScene::createStaticEnvironment()
  227. {
  228. int strideInBytes = 9*sizeof(float);
  229. int numVertices = sizeof(cube_vertices)/strideInBytes;
  230. int numIndices = sizeof(cube_indices)/sizeof(int);
  231. //int shapeId = ci.m_instancingRenderer->registerShape(&cube_vertices[0],numVertices,cube_indices,numIndices);
  232. int shapeId = m_instancingRenderer->registerShape(&cube_vertices[0],numVertices,cube_indices,numIndices);
  233. int group=1;
  234. int mask=1;
  235. int index=0;
  236. {
  237. b3Vector4 scaling=b3MakeVector4(400,400,400,1);
  238. int colIndex = m_data->m_np->registerConvexHullShape(&cube_vertices[0],strideInBytes,numVertices, scaling);
  239. b3Vector3 position=b3MakeVector3(0,-400,0);
  240. b3Quaternion orn(0,0,0,1);
  241. b3Vector4 color=b3MakeVector4(0,0,1,1);
  242. int id = m_instancingRenderer->registerGraphicsInstance(shapeId,position,orn,color,scaling);
  243. int pid = m_data->m_rigidBodyPipeline->registerPhysicsInstance(0.f,position,orn,colIndex,index,false);
  244. }
  245. }
  246. void GpuConvexPlaneScene::createStaticEnvironment()
  247. {
  248. int strideInBytes = 9*sizeof(float);
  249. int numVertices = sizeof(cube_vertices)/strideInBytes;
  250. int numIndices = sizeof(cube_indices)/sizeof(int);
  251. //int shapeId = ci.m_instancingRenderer->registerShape(&cube_vertices[0],numVertices,cube_indices,numIndices);
  252. int shapeId = m_guiHelper->getRenderInterface()->registerShape(&cube_vertices[0],numVertices,cube_indices,numIndices);
  253. int group=1;
  254. int mask=1;
  255. int index=0;
  256. {
  257. b3Vector4 scaling=b3MakeVector4(400,400,400,1);
  258. int colIndex = m_data->m_np->registerConvexHullShape(&cube_vertices[0],strideInBytes,numVertices, scaling);
  259. b3Vector3 position=b3MakeVector3(0,-400,0);
  260. b3Quaternion orn(0,0,0,1);
  261. b3Vector4 color=b3MakeVector4(0,0,1,1);
  262. int id = m_guiHelper->getRenderInterface()->registerGraphicsInstance(shapeId,position,orn,color,scaling);
  263. int pid = m_data->m_rigidBodyPipeline->registerPhysicsInstance(0.f,position,orn,colIndex,index,false);
  264. }
  265. }
  266. /*
  267. void GpuConvexPlaneScene::createStaticEnvironment(const ConstructionInfo& ci)
  268. {
  269. int strideInBytes = 9*sizeof(float);
  270. int numVertices = sizeof(cube_vertices)/strideInBytes;
  271. int numIndices = sizeof(cube_indices)/sizeof(int);
  272. //int shapeId = ci.m_instancingRenderer->registerShape(&cube_vertices[0],numVertices,cube_indices,numIndices);
  273. int shapeId = ci.m_instancingRenderer->registerShape(&cube_vertices[0],numVertices,cube_indices,numIndices);
  274. int group=1;
  275. int mask=1;
  276. int index=0;
  277. {
  278. b3Vector4 scaling=b3MakeVector4(100,0.001,100,1);
  279. //int colIndex = m_data->m_np->registerConvexHullShape(&cube_vertices[0],strideInBytes,numVertices, scaling);
  280. b3Vector3 normal=b3MakeVector3(0,1,0);
  281. float constant=0.f;
  282. int colIndex = m_data->m_np->registerPlaneShape(normal,constant);//>registerConvexHullShape(&cube_vertices[0],strideInBytes,numVertices, scaling);
  283. b3Vector3 position=b3MakeVector3(0,0,0);
  284. b3Quaternion orn(0,0,0,1);
  285. b3Vector4 color=b3MakeVector4(0,0,1,1);
  286. int id = ci.m_instancingRenderer->registerGraphicsInstance(shapeId,position,orn,color,scaling);
  287. int pid = m_data->m_rigidBodyPipeline->registerPhysicsInstance(0.f,position,orn,colIndex,index,false);
  288. }
  289. }
  290. */
  291. struct TetraBunny
  292. {
  293. #include "bunny.inl"
  294. };
  295. struct TetraCube
  296. {
  297. #include "cube.inl"
  298. };
  299. static int nextLine(const char* buffer)
  300. {
  301. int numBytesRead=0;
  302. while (*buffer != '\n')
  303. {
  304. buffer++;
  305. numBytesRead++;
  306. }
  307. if (buffer[0]==0x0a)
  308. {
  309. buffer++;
  310. numBytesRead++;
  311. }
  312. return numBytesRead;
  313. }
  314. static float mytetra_vertices[] =
  315. {
  316. -1.f, 0, -1.f, 0.5f, 0, 1,0, 0,0,
  317. -1.f, 0, 1.f, 0.5f, 0, 1,0, 1,0,
  318. 1.f, 0, 1.f, 0.5f, 0, 1,0, 1,1,
  319. 1.f, 0, -1.f, 0.5f, 0, 1,0, 0,1
  320. };
  321. static int mytetra_indices[]=
  322. {
  323. 0,1,2,
  324. 3,1,2,3,2,0,
  325. 3,0,1
  326. };
  327. /* Create from TetGen .ele, .face, .node data */
  328. void GpuTetraScene::createFromTetGenData(const char* ele,
  329. const char* node)
  330. {
  331. b3Scalar scaling(10);
  332. b3AlignedObjectArray<b3Vector3> pos;
  333. int nnode=0;
  334. int ndims=0;
  335. int nattrb=0;
  336. int hasbounds=0;
  337. int result = sscanf(node,"%d %d %d %d",&nnode,&ndims,&nattrb,&hasbounds);
  338. result = sscanf(node,"%d %d %d %d",&nnode,&ndims,&nattrb,&hasbounds);
  339. node += nextLine(node);
  340. //b3AlignedObjectArray<b3Vector3> rigidBodyPositions;
  341. //b3AlignedObjectArray<int> rigidBodyIds;
  342. pos.resize(nnode);
  343. for(int i=0;i<pos.size();++i)
  344. {
  345. int index=0;
  346. //int bound=0;
  347. float x,y,z;
  348. sscanf(node,"%d %f %f %f",&index,&x,&y,&z);
  349. // sn>>index;
  350. // sn>>x;sn>>y;sn>>z;
  351. node += nextLine(node);
  352. //for(int j=0;j<nattrb;++j)
  353. // sn>>a;
  354. //if(hasbounds)
  355. // sn>>bound;
  356. pos[index].setX(b3Scalar(x)*scaling);
  357. pos[index].setY(b3Scalar(y)*scaling);
  358. pos[index].setZ(b3Scalar(z)*scaling);
  359. }
  360. if(ele&&ele[0])
  361. {
  362. int ntetra=0;
  363. int ncorner=0;
  364. int neattrb=0;
  365. sscanf(ele,"%d %d %d",&ntetra,&ncorner,&neattrb);
  366. ele += nextLine(ele);
  367. //se>>ntetra;se>>ncorner;se>>neattrb;
  368. for(int i=0;i<ntetra;++i)
  369. {
  370. int index=0;
  371. int ni[4];
  372. //se>>index;
  373. //se>>ni[0];se>>ni[1];se>>ni[2];se>>ni[3];
  374. sscanf(ele,"%d %d %d %d %d",&index,&ni[0],&ni[1],&ni[2],&ni[3]);
  375. ele+=nextLine(ele);
  376. b3Vector3 average=b3MakeVector3(0,0,0);
  377. for (int v=0;v<4;v++)
  378. {
  379. average+=pos[ni[v]];
  380. }
  381. average/=4;
  382. for (int v=0;v<4;v++)
  383. {
  384. b3Vector3 shiftedPos = pos[ni[v]]-average;
  385. mytetra_vertices[0+v*9] = shiftedPos.getX();
  386. mytetra_vertices[1+v*9] = shiftedPos.getY();
  387. mytetra_vertices[2+v*9] = shiftedPos.getZ();
  388. }
  389. //todo: subtract average
  390. int strideInBytes = 9*sizeof(float);
  391. int numVertices = sizeof(mytetra_vertices)/strideInBytes;
  392. int numIndices = sizeof(mytetra_indices)/sizeof(int);
  393. int shapeId = m_instancingRenderer->registerShape(&mytetra_vertices[0],numVertices,mytetra_indices,numIndices);
  394. int group=1;
  395. int mask=1;
  396. {
  397. b3Vector4 scaling=b3MakeVector4(1,1,1,1);
  398. int colIndex = m_data->m_np->registerConvexHullShape(&mytetra_vertices[0],strideInBytes,numVertices, scaling);
  399. b3Vector3 position=b3MakeVector3(0,150,0);
  400. // position+=average;//*1.2;//*2;
  401. position+=average*1.2;//*2;
  402. //rigidBodyPositions.push_back(position);
  403. b3Quaternion orn(0,0,0,1);
  404. static int curColor=0;
  405. b3Vector4 color = colors[curColor++];
  406. curColor&=3;
  407. int id = m_instancingRenderer->registerGraphicsInstance(shapeId,position,orn,color,scaling);
  408. int pid = m_data->m_rigidBodyPipeline->registerPhysicsInstance(1.f,position,orn,colIndex,0,false);
  409. //rigidBodyIds.push_back(pid);
  410. }
  411. //for(int j=0;j<neattrb;++j)
  412. // se>>a;
  413. //psb->appendTetra(ni[0],ni[1],ni[2],ni[3]);
  414. }
  415. // printf("Nodes: %u\r\n",psb->m_nodes.size());
  416. // printf("Links: %u\r\n",psb->m_links.size());
  417. // printf("Faces: %u\r\n",psb->m_faces.size());
  418. // printf("Tetras: %u\r\n",psb->m_tetras.size());
  419. }
  420. m_data->m_rigidBodyPipeline->writeAllInstancesToGpu();
  421. m_data->m_np->writeAllBodiesToGpu();
  422. m_data->m_bp->writeAabbsToGpu();
  423. m_data->m_rigidBodyPipeline->setupGpuAabbsFull();
  424. m_data->m_bp->calculateOverlappingPairs(m_data->m_config.m_maxBroadphasePairs);
  425. int numPairs = m_data->m_bp->getNumOverlap();
  426. cl_mem pairs = m_data->m_bp->getOverlappingPairBuffer();
  427. b3OpenCLArray<b3Int2> clPairs(m_clData->m_clContext,m_clData->m_clQueue);
  428. clPairs.setFromOpenCLBuffer(pairs,numPairs);
  429. b3AlignedObjectArray<b3Int2> allPairs;
  430. clPairs.copyToHost(allPairs);
  431. for (int p=0;p<allPairs.size();p++)
  432. {
  433. b3Vector3 posA,posB;
  434. b3Quaternion ornA,ornB;
  435. int bodyIndexA = allPairs[p].x;
  436. int bodyIndexB = allPairs[p].y;
  437. m_data->m_np->getObjectTransformFromCpu(posA,ornA,bodyIndexA);
  438. m_data->m_np->getObjectTransformFromCpu(posB,ornB,bodyIndexB);
  439. b3Vector3 pivotWorld = (posA+posB)*0.5f;
  440. b3Transform transA,transB;
  441. transA.setIdentity();
  442. transA.setOrigin(posA);
  443. transA.setRotation(ornA);
  444. transB.setIdentity();
  445. transB.setOrigin(posB);
  446. transB.setRotation(ornB);
  447. b3Vector3 pivotInA = transA.inverse()*pivotWorld;
  448. b3Vector3 pivotInB = transB.inverse()*pivotWorld;
  449. b3Transform frameInA,frameInB;
  450. frameInA.setIdentity();
  451. frameInB.setIdentity();
  452. frameInA.setOrigin(pivotInA);
  453. frameInB.setOrigin(pivotInB);
  454. b3Quaternion relTargetAB = frameInA.getRotation()*frameInB.getRotation().inverse();
  455. //c = new b3FixedConstraint(pid,prevBody,frameInA,frameInB);
  456. float breakingThreshold = 45;//37.f;
  457. //c->setBreakingImpulseThreshold(37.1);
  458. bool useGPU = true;
  459. if (useGPU)
  460. {
  461. int cid = m_data->m_rigidBodyPipeline->createFixedConstraint(bodyIndexA,bodyIndexB,pivotInA,pivotInB,relTargetAB,breakingThreshold);
  462. } else
  463. {
  464. b3FixedConstraint* c = new b3FixedConstraint(bodyIndexA,bodyIndexB,frameInA,frameInB);
  465. c->setBreakingImpulseThreshold(breakingThreshold);
  466. m_data->m_rigidBodyPipeline->addConstraint(c);
  467. }
  468. }
  469. printf("numPairs = %d\n",numPairs);
  470. }
  471. int GpuTetraScene::createDynamicsObjects()
  472. {
  473. //createFromTetGenData(TetraCube::getElements(),TetraCube::getNodes());
  474. createFromTetGenData(TetraBunny::getElements(),TetraBunny::getNodes());
  475. return 0;
  476. }
  477. class CommonExampleInterface* OpenCLBoxBoxCreateFunc(struct CommonExampleOptions& options)
  478. {
  479. return new GpuBoxPlaneScene(options.m_guiHelper);
  480. }