GpuRigidBodyDemo.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512
  1. #include "GpuRigidBodyDemo.h"
  2. #include "../OpenGLWindow/ShapeData.h"
  3. #include "../OpenGLWindow/GLInstancingRenderer.h"
  4. #include "Bullet3Common/b3Quaternion.h"
  5. #include "../CommonInterfaces/CommonWindowInterface.h"
  6. #include "Bullet3OpenCL/BroadphaseCollision/b3GpuSapBroadphase.h"
  7. #include "Bullet3OpenCL/BroadphaseCollision/b3GpuGridBroadphase.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 "Bullet3Collision/BroadPhaseCollision/b3DynamicBvhBroadphase.h"
  18. #include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
  19. #include "Bullet3OpenCL/RigidBody/b3GpuNarrowPhaseInternalData.h"
  20. #include "stb_image/stb_image.h"
  21. #include "../OpenGLWindow/GLPrimitiveRenderer.h"
  22. extern int gPreferredOpenCLDeviceIndex;
  23. extern int gPreferredOpenCLPlatformIndex;
  24. extern int gGpuArraySizeX;
  25. extern int gGpuArraySizeY;
  26. extern int gGpuArraySizeZ;
  27. static b3KeyboardCallback oldCallback = 0;
  28. extern bool gReset;
  29. bool useUniformGrid = false;
  30. bool convertOnCpu = false;
  31. #define MSTRINGIFY(A) #A
  32. static const char* s_rigidBodyKernelString = MSTRINGIFY(
  33. typedef struct
  34. {
  35. float4 m_pos;
  36. float4 m_quat;
  37. float4 m_linVel;
  38. float4 m_angVel;
  39. unsigned int m_collidableIdx;
  40. float m_invMass;
  41. float m_restituitionCoeff;
  42. float m_frictionCoeff;
  43. } Body;
  44. __kernel void
  45. copyTransformsToVBOKernel( __global Body* gBodies, __global float4* posOrnColor, const int numNodes)
  46. {
  47. int nodeID = get_global_id(0);
  48. if( nodeID < numNodes )
  49. {
  50. posOrnColor[nodeID] = (float4) (gBodies[nodeID].m_pos.xyz,1.0);
  51. posOrnColor[nodeID + numNodes] = gBodies[nodeID].m_quat;
  52. }
  53. }
  54. );
  55. GpuRigidBodyDemo::GpuRigidBodyDemo(GUIHelperInterface* helper)
  56. :CommonOpenCLBase(helper),
  57. m_instancingRenderer(0),
  58. m_window(0)
  59. {
  60. if (helper->getRenderInterface()->getInternalData())
  61. {
  62. m_instancingRenderer = (GLInstancingRenderer*)helper->getRenderInterface();
  63. } else
  64. {
  65. m_instancingRenderer = 0;
  66. }
  67. m_window = helper->getAppInterface()->m_window;
  68. m_data = new GpuRigidBodyDemoInternalData;
  69. }
  70. GpuRigidBodyDemo::~GpuRigidBodyDemo()
  71. {
  72. delete m_data;
  73. }
  74. static void PairKeyboardCallback(int key, int state)
  75. {
  76. if (key=='R' && state)
  77. {
  78. //gReset = true;
  79. }
  80. //b3DefaultKeyboardCallback(key,state);
  81. oldCallback(key,state);
  82. }
  83. void GpuRigidBodyDemo::setupScene()
  84. {
  85. }
  86. void GpuRigidBodyDemo::initPhysics()
  87. {
  88. initCL(gPreferredOpenCLDeviceIndex,gPreferredOpenCLPlatformIndex);
  89. m_guiHelper->setUpAxis(1);
  90. if (m_clData->m_clContext)
  91. {
  92. int errNum=0;
  93. cl_program rbProg=0;
  94. m_data->m_copyTransformsToVBOKernel = b3OpenCLUtils::compileCLKernelFromString(m_clData->m_clContext,m_clData->m_clDevice,s_rigidBodyKernelString,"copyTransformsToVBOKernel",&errNum,rbProg);
  95. m_data->m_config.m_maxConvexBodies = b3Max(m_data->m_config.m_maxConvexBodies,gGpuArraySizeX*gGpuArraySizeY*gGpuArraySizeZ+10);
  96. m_data->m_config.m_maxConvexShapes = m_data->m_config.m_maxConvexBodies;
  97. int maxPairsPerBody = 16;
  98. m_data->m_config.m_maxBroadphasePairs = maxPairsPerBody*m_data->m_config.m_maxConvexBodies;
  99. m_data->m_config.m_maxContactCapacity = m_data->m_config.m_maxBroadphasePairs;
  100. b3GpuNarrowPhase* np = new b3GpuNarrowPhase(m_clData->m_clContext,m_clData->m_clDevice,m_clData->m_clQueue,m_data->m_config);
  101. b3GpuBroadphaseInterface* bp =0;
  102. if (useUniformGrid)
  103. {
  104. bp = new b3GpuGridBroadphase(m_clData->m_clContext,m_clData->m_clDevice,m_clData->m_clQueue);
  105. } else
  106. {
  107. bp = new b3GpuSapBroadphase(m_clData->m_clContext,m_clData->m_clDevice,m_clData->m_clQueue);
  108. }
  109. m_data->m_np = np;
  110. m_data->m_bp = bp;
  111. m_data->m_broadphaseDbvt = new b3DynamicBvhBroadphase(m_data->m_config.m_maxConvexBodies);
  112. m_data->m_rigidBodyPipeline = new b3GpuRigidBodyPipeline(m_clData->m_clContext,m_clData->m_clDevice,m_clData->m_clQueue, np, bp,m_data->m_broadphaseDbvt,m_data->m_config);
  113. setupScene();
  114. m_data->m_rigidBodyPipeline->writeAllInstancesToGpu();
  115. np->writeAllBodiesToGpu();
  116. bp->writeAabbsToGpu();
  117. }
  118. m_guiHelper->getRenderInterface()->writeTransforms();
  119. }
  120. void GpuRigidBodyDemo::exitPhysics()
  121. {
  122. destroyScene();
  123. delete m_data->m_instancePosOrnColor;
  124. delete m_data->m_rigidBodyPipeline;
  125. delete m_data->m_broadphaseDbvt;
  126. delete m_data->m_np;
  127. m_data->m_np = 0;
  128. delete m_data->m_bp;
  129. m_data->m_bp = 0;
  130. exitCL();
  131. }
  132. void GpuRigidBodyDemo::renderScene()
  133. {
  134. m_guiHelper->getRenderInterface()->renderScene();
  135. }
  136. void GpuRigidBodyDemo::stepSimulation(float deltaTime)
  137. {
  138. if (!m_instancingRenderer)
  139. return;
  140. bool animate=true;
  141. int numObjects= m_data->m_rigidBodyPipeline->getNumBodies();
  142. //printf("numObjects=%d\n",numObjects);
  143. if (numObjects > m_instancingRenderer->getInstanceCapacity())
  144. {
  145. static bool once = true;
  146. if (once)
  147. {
  148. once=false;
  149. b3Assert(0);
  150. b3Error("m_instancingRenderer out-of-memory\n");
  151. }
  152. numObjects = m_instancingRenderer->getInstanceCapacity();
  153. }
  154. GLint err = glGetError();
  155. assert(err==GL_NO_ERROR);
  156. b3Vector4* positions = 0;
  157. if (animate && numObjects)
  158. {
  159. B3_PROFILE("gl2cl");
  160. if (!m_data->m_instancePosOrnColor)
  161. {
  162. GLuint vbo = m_instancingRenderer->getInternalData()->m_vbo;
  163. int arraySizeInBytes = numObjects * (3)*sizeof(b3Vector4);
  164. glBindBuffer(GL_ARRAY_BUFFER, vbo);
  165. cl_bool blocking= CL_TRUE;
  166. positions= (b3Vector4*)glMapBufferRange( GL_ARRAY_BUFFER,m_instancingRenderer->getMaxShapeCapacity(),arraySizeInBytes, GL_MAP_READ_BIT );//GL_READ_WRITE);//GL_WRITE_ONLY
  167. GLint err = glGetError();
  168. assert(err==GL_NO_ERROR);
  169. m_data->m_instancePosOrnColor = new b3OpenCLArray<b3Vector4>(m_clData->m_clContext,m_clData->m_clQueue);
  170. m_data->m_instancePosOrnColor->resize(3*numObjects);
  171. m_data->m_instancePosOrnColor->copyFromHostPointer(positions,3*numObjects,0);
  172. glUnmapBuffer( GL_ARRAY_BUFFER);
  173. err = glGetError();
  174. assert(err==GL_NO_ERROR);
  175. }
  176. }
  177. {
  178. B3_PROFILE("stepSimulation");
  179. m_data->m_rigidBodyPipeline->stepSimulation(1./60.f);
  180. }
  181. if (numObjects)
  182. {
  183. if (convertOnCpu)
  184. {
  185. b3GpuNarrowPhaseInternalData* npData = m_data->m_np->getInternalData();
  186. npData->m_bodyBufferGPU->copyToHost(*npData->m_bodyBufferCPU);
  187. b3AlignedObjectArray<b3Vector4> vboCPU;
  188. m_data->m_instancePosOrnColor->copyToHost(vboCPU);
  189. for (int i=0;i<numObjects;i++)
  190. {
  191. b3Vector4 pos = (const b3Vector4&)npData->m_bodyBufferCPU->at(i).m_pos;
  192. b3Quat orn = npData->m_bodyBufferCPU->at(i).m_quat;
  193. pos.w = 1.f;
  194. vboCPU[i] = pos;
  195. vboCPU[i + numObjects] = (b3Vector4&)orn;
  196. }
  197. m_data->m_instancePosOrnColor->copyFromHost(vboCPU);
  198. } else
  199. {
  200. B3_PROFILE("cl2gl_convert");
  201. int ciErrNum = 0;
  202. cl_mem bodies = m_data->m_rigidBodyPipeline->getBodyBuffer();
  203. b3LauncherCL launch(m_clData->m_clQueue,m_data->m_copyTransformsToVBOKernel,"m_copyTransformsToVBOKernel");
  204. launch.setBuffer(bodies);
  205. launch.setBuffer(m_data->m_instancePosOrnColor->getBufferCL());
  206. launch.setConst(numObjects);
  207. launch.launch1D(numObjects);
  208. oclCHECKERROR(ciErrNum, CL_SUCCESS);
  209. }
  210. }
  211. if (animate && numObjects)
  212. {
  213. B3_PROFILE("cl2gl_upload");
  214. GLint err = glGetError();
  215. assert(err==GL_NO_ERROR);
  216. GLuint vbo = m_instancingRenderer->getInternalData()->m_vbo;
  217. int arraySizeInBytes = numObjects * (3)*sizeof(b3Vector4);
  218. glBindBuffer(GL_ARRAY_BUFFER, vbo);
  219. cl_bool blocking= CL_TRUE;
  220. positions= (b3Vector4*)glMapBufferRange( GL_ARRAY_BUFFER,m_instancingRenderer->getMaxShapeCapacity(),arraySizeInBytes, GL_MAP_WRITE_BIT );//GL_READ_WRITE);//GL_WRITE_ONLY
  221. err = glGetError();
  222. assert(err==GL_NO_ERROR);
  223. m_data->m_instancePosOrnColor->copyToHostPointer(positions,3*numObjects,0);
  224. glUnmapBuffer( GL_ARRAY_BUFFER);
  225. err = glGetError();
  226. assert(err==GL_NO_ERROR);
  227. }
  228. }
  229. b3Vector3 GpuRigidBodyDemo::getRayTo(int x,int y)
  230. {
  231. if (!m_instancingRenderer)
  232. return b3MakeVector3(0,0,0);
  233. float top = 1.f;
  234. float bottom = -1.f;
  235. float nearPlane = 1.f;
  236. float tanFov = (top-bottom)*0.5f / nearPlane;
  237. float fov = b3Scalar(2.0) * b3Atan(tanFov);
  238. b3Vector3 camPos,camTarget;
  239. m_instancingRenderer->getActiveCamera()->getCameraPosition(camPos);
  240. m_instancingRenderer->getActiveCamera()->getCameraTargetPosition(camTarget);
  241. b3Vector3 rayFrom = camPos;
  242. b3Vector3 rayForward = (camTarget-camPos);
  243. rayForward.normalize();
  244. float farPlane = 10000.f;
  245. rayForward*= farPlane;
  246. b3Vector3 rightOffset;
  247. b3Vector3 m_cameraUp=b3MakeVector3(0,1,0);
  248. b3Vector3 vertical = m_cameraUp;
  249. b3Vector3 hor;
  250. hor = rayForward.cross(vertical);
  251. hor.normalize();
  252. vertical = hor.cross(rayForward);
  253. vertical.normalize();
  254. float tanfov = tanf(0.5f*fov);
  255. hor *= 2.f * farPlane * tanfov;
  256. vertical *= 2.f * farPlane * tanfov;
  257. b3Scalar aspect;
  258. float width = m_instancingRenderer->getScreenWidth();
  259. float height = m_instancingRenderer->getScreenHeight();
  260. aspect = width / height;
  261. hor*=aspect;
  262. b3Vector3 rayToCenter = rayFrom + rayForward;
  263. b3Vector3 dHor = hor * 1.f/width;
  264. b3Vector3 dVert = vertical * 1.f/height;
  265. b3Vector3 rayTo = rayToCenter - 0.5f * hor + 0.5f * vertical;
  266. rayTo += b3Scalar(x) * dHor;
  267. rayTo -= b3Scalar(y) * dVert;
  268. return rayTo;
  269. }
  270. unsigned char* GpuRigidBodyDemo::loadImage(const char* fileName, int& width, int& height, int& n)
  271. {
  272. unsigned char *data = stbi_load(fileName, &width, &height, &n, 3);
  273. return data;
  274. }
  275. bool GpuRigidBodyDemo::keyboardCallback(int key, int state)
  276. {
  277. if (m_data)
  278. {
  279. if (key==B3G_ALT )
  280. {
  281. m_data->m_altPressed = state;
  282. }
  283. if (key==B3G_CONTROL )
  284. {
  285. m_data->m_controlPressed = state;
  286. }
  287. }
  288. return false;
  289. }
  290. bool GpuRigidBodyDemo::mouseMoveCallback(float x,float y)
  291. {
  292. if (!m_instancingRenderer)
  293. return false;
  294. if (m_data->m_altPressed!=0 || m_data->m_controlPressed!=0)
  295. return false;
  296. if (m_data->m_pickBody>=0 && m_data->m_pickConstraint>=0)
  297. {
  298. m_data->m_rigidBodyPipeline->removeConstraintByUid(m_data->m_pickConstraint);
  299. b3Vector3 newRayTo = getRayTo(x,y);
  300. b3Vector3 rayFrom;
  301. b3Vector3 oldPivotInB = m_data->m_pickPivotInB;
  302. b3Vector3 newPivotB;
  303. m_guiHelper->getRenderInterface()->getActiveCamera()->getCameraPosition(rayFrom);
  304. b3Vector3 dir = newRayTo-rayFrom;
  305. dir.normalize();
  306. dir *= m_data->m_pickDistance;
  307. newPivotB = rayFrom + dir;
  308. m_data->m_pickPivotInB = newPivotB;
  309. m_data->m_rigidBodyPipeline->copyConstraintsToHost();
  310. m_data->m_pickConstraint = m_data->m_rigidBodyPipeline->createPoint2PointConstraint(m_data->m_pickBody,m_data->m_pickFixedBody,m_data->m_pickPivotInA,m_data->m_pickPivotInB,1e30);
  311. m_data->m_rigidBodyPipeline->writeAllInstancesToGpu();
  312. return true;
  313. }
  314. return false;
  315. }
  316. bool GpuRigidBodyDemo::mouseButtonCallback(int button, int state, float x, float y)
  317. {
  318. if (!m_instancingRenderer)
  319. return false;
  320. if (state==1)
  321. {
  322. if(button==0 && (m_data->m_altPressed==0 && m_data->m_controlPressed==0))
  323. {
  324. b3AlignedObjectArray<b3RayInfo> rays;
  325. b3AlignedObjectArray<b3RayHit> hitResults;
  326. b3Vector3 camPos;
  327. m_guiHelper->getRenderInterface()->getActiveCamera()->getCameraPosition(camPos);
  328. b3RayInfo ray;
  329. ray.m_from = camPos;
  330. ray.m_to = getRayTo(x,y);
  331. rays.push_back(ray);
  332. b3RayHit hit;
  333. hit.m_hitFraction = 1.f;
  334. hitResults.push_back(hit);
  335. m_data->m_rigidBodyPipeline->castRays(rays,hitResults);
  336. if (hitResults[0].m_hitFraction<1.f)
  337. {
  338. int hitBodyA = hitResults[0].m_hitBody;
  339. if (m_data->m_np->getBodiesCpu()[hitBodyA].m_invMass)
  340. {
  341. //printf("hit!\n");
  342. m_data->m_np->readbackAllBodiesToCpu();
  343. m_data->m_pickBody = hitBodyA;
  344. //pivotInA
  345. b3Vector3 pivotInB;
  346. pivotInB.setInterpolate3(ray.m_from,ray.m_to,hitResults[0].m_hitFraction);
  347. b3Vector3 posA;
  348. b3Quaternion ornA;
  349. m_data->m_np->getObjectTransformFromCpu(posA,ornA,hitBodyA);
  350. b3Transform tr;
  351. tr.setOrigin(posA);
  352. tr.setRotation(ornA);
  353. b3Vector3 pivotInA = tr.inverse()*pivotInB;
  354. if (m_data->m_pickFixedBody<0)
  355. {
  356. b3Vector3 pos=b3MakeVector3(0,0,0);
  357. b3Quaternion orn(0,0,0,1);
  358. int fixedSphere = m_data->m_np->registerConvexHullShape(0,0,0,0);//>registerSphereShape(0.1);
  359. m_data->m_pickFixedBody = m_data->m_rigidBodyPipeline->registerPhysicsInstance(0,pos,orn,fixedSphere,0,false);
  360. m_data->m_rigidBodyPipeline->writeAllInstancesToGpu();
  361. m_data->m_bp->writeAabbsToGpu();
  362. if (m_data->m_pickGraphicsShapeIndex<0)
  363. {
  364. int strideInBytes = 9*sizeof(float);
  365. int numVertices = sizeof(point_sphere_vertices)/strideInBytes;
  366. int numIndices = sizeof(point_sphere_indices)/sizeof(int);
  367. m_data->m_pickGraphicsShapeIndex = m_guiHelper->getRenderInterface()->registerShape(&point_sphere_vertices[0],numVertices,point_sphere_indices,numIndices,B3_GL_POINTS);
  368. float color[4] ={1,0,0,1};
  369. float scaling[4]={1,1,1,1};
  370. m_data->m_pickGraphicsShapeInstance = m_guiHelper->getRenderInterface()->registerGraphicsInstance(m_data->m_pickGraphicsShapeIndex,pivotInB,orn,color,scaling);
  371. m_guiHelper->getRenderInterface()->writeTransforms();
  372. delete m_data->m_instancePosOrnColor;
  373. m_data->m_instancePosOrnColor=0;
  374. } else
  375. {
  376. m_guiHelper->getRenderInterface()->writeSingleInstanceTransformToCPU(pivotInB,orn,m_data->m_pickGraphicsShapeInstance);
  377. if (this->m_instancingRenderer)
  378. m_instancingRenderer->writeSingleInstanceTransformToGPU(pivotInB,orn,m_data->m_pickGraphicsShapeInstance);
  379. m_data->m_np->setObjectTransformCpu(pos,orn,m_data->m_pickFixedBody);
  380. }
  381. }
  382. pivotInB.w = 0.f;
  383. m_data->m_pickPivotInA = pivotInA;
  384. m_data->m_pickPivotInB = pivotInB;
  385. m_data->m_rigidBodyPipeline->copyConstraintsToHost();
  386. m_data->m_pickConstraint = m_data->m_rigidBodyPipeline->createPoint2PointConstraint(hitBodyA,m_data->m_pickFixedBody,pivotInA,pivotInB,1e30);//hitResults[0].m_hitResult0
  387. m_data->m_rigidBodyPipeline->writeAllInstancesToGpu();
  388. m_data->m_np->writeAllBodiesToGpu();
  389. m_data->m_pickDistance = (pivotInB-camPos).length();
  390. return true;
  391. }
  392. }
  393. }
  394. } else
  395. {
  396. if (button==0)
  397. {
  398. if (m_data->m_pickConstraint>=0)
  399. {
  400. m_data->m_rigidBodyPipeline->removeConstraintByUid(m_data->m_pickConstraint);
  401. m_data->m_pickConstraint=-1;
  402. }
  403. }
  404. }
  405. //printf("button=%d, state=%d\n",button,state);
  406. return false;
  407. }