b3CpuRigidBodyPipeline.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  1. #include "b3CpuRigidBodyPipeline.h"
  2. #include "Bullet3Dynamics/shared/b3IntegrateTransforms.h"
  3. #include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
  4. #include "Bullet3Collision/BroadPhaseCollision/b3DynamicBvhBroadphase.h"
  5. #include "Bullet3Collision/NarrowPhaseCollision/b3Config.h"
  6. #include "Bullet3Collision/NarrowPhaseCollision/b3CpuNarrowPhase.h"
  7. #include "Bullet3Collision/BroadPhaseCollision/shared/b3Aabb.h"
  8. #include "Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h"
  9. #include "Bullet3Common/b3Vector3.h"
  10. #include "Bullet3Dynamics/shared/b3ContactConstraint4.h"
  11. #include "Bullet3Dynamics/shared/b3Inertia.h"
  12. struct b3CpuRigidBodyPipelineInternalData
  13. {
  14. b3AlignedObjectArray<b3RigidBodyData> m_rigidBodies;
  15. b3AlignedObjectArray<b3Inertia> m_inertias;
  16. b3AlignedObjectArray<b3Aabb> m_aabbWorldSpace;
  17. b3DynamicBvhBroadphase* m_bp;
  18. b3CpuNarrowPhase* m_np;
  19. b3Config m_config;
  20. };
  21. b3CpuRigidBodyPipeline::b3CpuRigidBodyPipeline(class b3CpuNarrowPhase* narrowphase, struct b3DynamicBvhBroadphase* broadphaseDbvt, const b3Config& config)
  22. {
  23. m_data = new b3CpuRigidBodyPipelineInternalData;
  24. m_data->m_np = narrowphase;
  25. m_data->m_bp = broadphaseDbvt;
  26. m_data->m_config = config;
  27. }
  28. b3CpuRigidBodyPipeline::~b3CpuRigidBodyPipeline()
  29. {
  30. delete m_data;
  31. }
  32. void b3CpuRigidBodyPipeline::updateAabbWorldSpace()
  33. {
  34. for (int i = 0; i < this->getNumBodies(); i++)
  35. {
  36. b3RigidBodyData* body = &m_data->m_rigidBodies[i];
  37. b3Float4 position = body->m_pos;
  38. b3Quat orientation = body->m_quat;
  39. int collidableIndex = body->m_collidableIdx;
  40. b3Collidable& collidable = m_data->m_np->getCollidableCpu(collidableIndex);
  41. int shapeIndex = collidable.m_shapeIndex;
  42. if (shapeIndex >= 0)
  43. {
  44. b3Aabb localAabb = m_data->m_np->getLocalSpaceAabb(shapeIndex);
  45. b3Aabb& worldAabb = m_data->m_aabbWorldSpace[i];
  46. float margin = 0.f;
  47. b3TransformAabb2(localAabb.m_minVec, localAabb.m_maxVec, margin, position, orientation, &worldAabb.m_minVec, &worldAabb.m_maxVec);
  48. m_data->m_bp->setAabb(i, worldAabb.m_minVec, worldAabb.m_maxVec, 0);
  49. }
  50. }
  51. }
  52. void b3CpuRigidBodyPipeline::computeOverlappingPairs()
  53. {
  54. int numPairs = m_data->m_bp->getOverlappingPairCache()->getNumOverlappingPairs();
  55. m_data->m_bp->calculateOverlappingPairs();
  56. numPairs = m_data->m_bp->getOverlappingPairCache()->getNumOverlappingPairs();
  57. printf("numPairs=%d\n", numPairs);
  58. }
  59. void b3CpuRigidBodyPipeline::computeContactPoints()
  60. {
  61. b3AlignedObjectArray<b3Int4>& pairs = m_data->m_bp->getOverlappingPairCache()->getOverlappingPairArray();
  62. m_data->m_np->computeContacts(pairs, m_data->m_aabbWorldSpace, m_data->m_rigidBodies);
  63. }
  64. void b3CpuRigidBodyPipeline::stepSimulation(float deltaTime)
  65. {
  66. //update world space aabb's
  67. updateAabbWorldSpace();
  68. //compute overlapping pairs
  69. computeOverlappingPairs();
  70. //compute contacts
  71. computeContactPoints();
  72. //solve contacts
  73. //update transforms
  74. integrate(deltaTime);
  75. }
  76. static inline float b3CalcRelVel(const b3Vector3& l0, const b3Vector3& l1, const b3Vector3& a0, const b3Vector3& a1,
  77. const b3Vector3& linVel0, const b3Vector3& angVel0, const b3Vector3& linVel1, const b3Vector3& angVel1)
  78. {
  79. return b3Dot(l0, linVel0) + b3Dot(a0, angVel0) + b3Dot(l1, linVel1) + b3Dot(a1, angVel1);
  80. }
  81. static inline void b3SetLinearAndAngular(const b3Vector3& n, const b3Vector3& r0, const b3Vector3& r1,
  82. b3Vector3& linear, b3Vector3& angular0, b3Vector3& angular1)
  83. {
  84. linear = -n;
  85. angular0 = -b3Cross(r0, n);
  86. angular1 = b3Cross(r1, n);
  87. }
  88. static inline void b3SolveContact(b3ContactConstraint4& cs,
  89. const b3Vector3& posA, b3Vector3& linVelA, b3Vector3& angVelA, float invMassA, const b3Matrix3x3& invInertiaA,
  90. const b3Vector3& posB, b3Vector3& linVelB, b3Vector3& angVelB, float invMassB, const b3Matrix3x3& invInertiaB,
  91. float maxRambdaDt[4], float minRambdaDt[4])
  92. {
  93. b3Vector3 dLinVelA;
  94. dLinVelA.setZero();
  95. b3Vector3 dAngVelA;
  96. dAngVelA.setZero();
  97. b3Vector3 dLinVelB;
  98. dLinVelB.setZero();
  99. b3Vector3 dAngVelB;
  100. dAngVelB.setZero();
  101. for (int ic = 0; ic < 4; ic++)
  102. {
  103. // dont necessary because this makes change to 0
  104. if (cs.m_jacCoeffInv[ic] == 0.f) continue;
  105. {
  106. b3Vector3 angular0, angular1, linear;
  107. b3Vector3 r0 = cs.m_worldPos[ic] - (b3Vector3&)posA;
  108. b3Vector3 r1 = cs.m_worldPos[ic] - (b3Vector3&)posB;
  109. b3SetLinearAndAngular((const b3Vector3&)-cs.m_linear, (const b3Vector3&)r0, (const b3Vector3&)r1, linear, angular0, angular1);
  110. float rambdaDt = b3CalcRelVel((const b3Vector3&)cs.m_linear, (const b3Vector3&)-cs.m_linear, angular0, angular1,
  111. linVelA, angVelA, linVelB, angVelB) +
  112. cs.m_b[ic];
  113. rambdaDt *= cs.m_jacCoeffInv[ic];
  114. {
  115. float prevSum = cs.m_appliedRambdaDt[ic];
  116. float updated = prevSum;
  117. updated += rambdaDt;
  118. updated = b3Max(updated, minRambdaDt[ic]);
  119. updated = b3Min(updated, maxRambdaDt[ic]);
  120. rambdaDt = updated - prevSum;
  121. cs.m_appliedRambdaDt[ic] = updated;
  122. }
  123. b3Vector3 linImp0 = invMassA * linear * rambdaDt;
  124. b3Vector3 linImp1 = invMassB * (-linear) * rambdaDt;
  125. b3Vector3 angImp0 = (invInertiaA * angular0) * rambdaDt;
  126. b3Vector3 angImp1 = (invInertiaB * angular1) * rambdaDt;
  127. #ifdef _WIN32
  128. b3Assert(_finite(linImp0.getX()));
  129. b3Assert(_finite(linImp1.getX()));
  130. #endif
  131. {
  132. linVelA += linImp0;
  133. angVelA += angImp0;
  134. linVelB += linImp1;
  135. angVelB += angImp1;
  136. }
  137. }
  138. }
  139. }
  140. static inline void b3SolveFriction(b3ContactConstraint4& cs,
  141. const b3Vector3& posA, b3Vector3& linVelA, b3Vector3& angVelA, float invMassA, const b3Matrix3x3& invInertiaA,
  142. const b3Vector3& posB, b3Vector3& linVelB, b3Vector3& angVelB, float invMassB, const b3Matrix3x3& invInertiaB,
  143. float maxRambdaDt[4], float minRambdaDt[4])
  144. {
  145. if (cs.m_fJacCoeffInv[0] == 0 && cs.m_fJacCoeffInv[0] == 0) return;
  146. const b3Vector3& center = (const b3Vector3&)cs.m_center;
  147. b3Vector3 n = -(const b3Vector3&)cs.m_linear;
  148. b3Vector3 tangent[2];
  149. b3PlaneSpace1(n, tangent[0], tangent[1]);
  150. b3Vector3 angular0, angular1, linear;
  151. b3Vector3 r0 = center - posA;
  152. b3Vector3 r1 = center - posB;
  153. for (int i = 0; i < 2; i++)
  154. {
  155. b3SetLinearAndAngular(tangent[i], r0, r1, linear, angular0, angular1);
  156. float rambdaDt = b3CalcRelVel(linear, -linear, angular0, angular1,
  157. linVelA, angVelA, linVelB, angVelB);
  158. rambdaDt *= cs.m_fJacCoeffInv[i];
  159. {
  160. float prevSum = cs.m_fAppliedRambdaDt[i];
  161. float updated = prevSum;
  162. updated += rambdaDt;
  163. updated = b3Max(updated, minRambdaDt[i]);
  164. updated = b3Min(updated, maxRambdaDt[i]);
  165. rambdaDt = updated - prevSum;
  166. cs.m_fAppliedRambdaDt[i] = updated;
  167. }
  168. b3Vector3 linImp0 = invMassA * linear * rambdaDt;
  169. b3Vector3 linImp1 = invMassB * (-linear) * rambdaDt;
  170. b3Vector3 angImp0 = (invInertiaA * angular0) * rambdaDt;
  171. b3Vector3 angImp1 = (invInertiaB * angular1) * rambdaDt;
  172. #ifdef _WIN32
  173. b3Assert(_finite(linImp0.getX()));
  174. b3Assert(_finite(linImp1.getX()));
  175. #endif
  176. linVelA += linImp0;
  177. angVelA += angImp0;
  178. linVelB += linImp1;
  179. angVelB += angImp1;
  180. }
  181. { // angular damping for point constraint
  182. b3Vector3 ab = (posB - posA).normalized();
  183. b3Vector3 ac = (center - posA).normalized();
  184. if (b3Dot(ab, ac) > 0.95f || (invMassA == 0.f || invMassB == 0.f))
  185. {
  186. float angNA = b3Dot(n, angVelA);
  187. float angNB = b3Dot(n, angVelB);
  188. angVelA -= (angNA * 0.1f) * n;
  189. angVelB -= (angNB * 0.1f) * n;
  190. }
  191. }
  192. }
  193. struct b3SolveTask // : public ThreadPool::Task
  194. {
  195. b3SolveTask(b3AlignedObjectArray<b3RigidBodyData>& bodies,
  196. b3AlignedObjectArray<b3Inertia>& shapes,
  197. b3AlignedObjectArray<b3ContactConstraint4>& constraints,
  198. int start, int nConstraints,
  199. int maxNumBatches,
  200. b3AlignedObjectArray<int>* wgUsedBodies, int curWgidx)
  201. : m_bodies(bodies), m_shapes(shapes), m_constraints(constraints), m_wgUsedBodies(wgUsedBodies), m_curWgidx(curWgidx), m_start(start), m_nConstraints(nConstraints), m_solveFriction(true), m_maxNumBatches(maxNumBatches)
  202. {
  203. }
  204. unsigned short int getType() { return 0; }
  205. void run(int tIdx)
  206. {
  207. b3AlignedObjectArray<int> usedBodies;
  208. //printf("run..............\n");
  209. for (int bb = 0; bb < m_maxNumBatches; bb++)
  210. {
  211. usedBodies.resize(0);
  212. for (int ic = m_nConstraints - 1; ic >= 0; ic--)
  213. //for(int ic=0; ic<m_nConstraints; ic++)
  214. {
  215. int i = m_start + ic;
  216. if (m_constraints[i].m_batchIdx != bb)
  217. continue;
  218. float frictionCoeff = b3GetFrictionCoeff(&m_constraints[i]);
  219. int aIdx = (int)m_constraints[i].m_bodyA;
  220. int bIdx = (int)m_constraints[i].m_bodyB;
  221. //int localBatch = m_constraints[i].m_batchIdx;
  222. b3RigidBodyData& bodyA = m_bodies[aIdx];
  223. b3RigidBodyData& bodyB = m_bodies[bIdx];
  224. #if 0
  225. if ((bodyA.m_invMass) && (bodyB.m_invMass))
  226. {
  227. // printf("aIdx=%d, bIdx=%d\n", aIdx,bIdx);
  228. }
  229. if (bIdx==10)
  230. {
  231. //printf("ic(b)=%d, localBatch=%d\n",ic,localBatch);
  232. }
  233. #endif
  234. if (aIdx == 10)
  235. {
  236. //printf("ic(a)=%d, localBatch=%d\n",ic,localBatch);
  237. }
  238. if (usedBodies.size() < (aIdx + 1))
  239. {
  240. usedBodies.resize(aIdx + 1, 0);
  241. }
  242. if (usedBodies.size() < (bIdx + 1))
  243. {
  244. usedBodies.resize(bIdx + 1, 0);
  245. }
  246. if (bodyA.m_invMass)
  247. {
  248. b3Assert(usedBodies[aIdx] == 0);
  249. usedBodies[aIdx]++;
  250. }
  251. if (bodyB.m_invMass)
  252. {
  253. b3Assert(usedBodies[bIdx] == 0);
  254. usedBodies[bIdx]++;
  255. }
  256. if (!m_solveFriction)
  257. {
  258. float maxRambdaDt[4] = {FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX};
  259. float minRambdaDt[4] = {0.f, 0.f, 0.f, 0.f};
  260. b3SolveContact(m_constraints[i], (b3Vector3&)bodyA.m_pos, (b3Vector3&)bodyA.m_linVel, (b3Vector3&)bodyA.m_angVel, bodyA.m_invMass, (const b3Matrix3x3&)m_shapes[aIdx].m_invInertiaWorld,
  261. (b3Vector3&)bodyB.m_pos, (b3Vector3&)bodyB.m_linVel, (b3Vector3&)bodyB.m_angVel, bodyB.m_invMass, (const b3Matrix3x3&)m_shapes[bIdx].m_invInertiaWorld,
  262. maxRambdaDt, minRambdaDt);
  263. }
  264. else
  265. {
  266. float maxRambdaDt[4] = {FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX};
  267. float minRambdaDt[4] = {0.f, 0.f, 0.f, 0.f};
  268. float sum = 0;
  269. for (int j = 0; j < 4; j++)
  270. {
  271. sum += m_constraints[i].m_appliedRambdaDt[j];
  272. }
  273. frictionCoeff = 0.7f;
  274. for (int j = 0; j < 4; j++)
  275. {
  276. maxRambdaDt[j] = frictionCoeff * sum;
  277. minRambdaDt[j] = -maxRambdaDt[j];
  278. }
  279. b3SolveFriction(m_constraints[i], (b3Vector3&)bodyA.m_pos, (b3Vector3&)bodyA.m_linVel, (b3Vector3&)bodyA.m_angVel, bodyA.m_invMass, (const b3Matrix3x3&)m_shapes[aIdx].m_invInertiaWorld,
  280. (b3Vector3&)bodyB.m_pos, (b3Vector3&)bodyB.m_linVel, (b3Vector3&)bodyB.m_angVel, bodyB.m_invMass, (const b3Matrix3x3&)m_shapes[bIdx].m_invInertiaWorld,
  281. maxRambdaDt, minRambdaDt);
  282. }
  283. }
  284. if (m_wgUsedBodies)
  285. {
  286. if (m_wgUsedBodies[m_curWgidx].size() < usedBodies.size())
  287. {
  288. m_wgUsedBodies[m_curWgidx].resize(usedBodies.size());
  289. }
  290. for (int i = 0; i < usedBodies.size(); i++)
  291. {
  292. if (usedBodies[i])
  293. {
  294. //printf("cell %d uses body %d\n", m_curWgidx,i);
  295. m_wgUsedBodies[m_curWgidx][i] = 1;
  296. }
  297. }
  298. }
  299. }
  300. }
  301. b3AlignedObjectArray<b3RigidBodyData>& m_bodies;
  302. b3AlignedObjectArray<b3Inertia>& m_shapes;
  303. b3AlignedObjectArray<b3ContactConstraint4>& m_constraints;
  304. b3AlignedObjectArray<int>* m_wgUsedBodies;
  305. int m_curWgidx;
  306. int m_start;
  307. int m_nConstraints;
  308. bool m_solveFriction;
  309. int m_maxNumBatches;
  310. };
  311. void b3CpuRigidBodyPipeline::solveContactConstraints()
  312. {
  313. int m_nIterations = 4;
  314. b3AlignedObjectArray<b3ContactConstraint4> contactConstraints;
  315. // const b3AlignedObjectArray<b3Contact4Data>& contacts = m_data->m_np->getContacts();
  316. int n = contactConstraints.size();
  317. //convert contacts...
  318. int maxNumBatches = 250;
  319. for (int iter = 0; iter < m_nIterations; iter++)
  320. {
  321. b3SolveTask task(m_data->m_rigidBodies, m_data->m_inertias, contactConstraints, 0, n, maxNumBatches, 0, 0);
  322. task.m_solveFriction = false;
  323. task.run(0);
  324. }
  325. for (int iter = 0; iter < m_nIterations; iter++)
  326. {
  327. b3SolveTask task(m_data->m_rigidBodies, m_data->m_inertias, contactConstraints, 0, n, maxNumBatches, 0, 0);
  328. task.m_solveFriction = true;
  329. task.run(0);
  330. }
  331. }
  332. void b3CpuRigidBodyPipeline::integrate(float deltaTime)
  333. {
  334. float angDamping = 0.f;
  335. b3Vector3 gravityAcceleration = b3MakeVector3(0, -9, 0);
  336. //integrate transforms (external forces/gravity should be moved into constraint solver)
  337. for (int i = 0; i < m_data->m_rigidBodies.size(); i++)
  338. {
  339. b3IntegrateTransform(&m_data->m_rigidBodies[i], deltaTime, angDamping, gravityAcceleration);
  340. }
  341. }
  342. int b3CpuRigidBodyPipeline::registerPhysicsInstance(float mass, const float* position, const float* orientation, int collidableIndex, int userData)
  343. {
  344. b3RigidBodyData body;
  345. int bodyIndex = m_data->m_rigidBodies.size();
  346. body.m_invMass = mass ? 1.f / mass : 0.f;
  347. body.m_angVel.setValue(0, 0, 0);
  348. body.m_collidableIdx = collidableIndex;
  349. body.m_frictionCoeff = 0.3f;
  350. body.m_linVel.setValue(0, 0, 0);
  351. body.m_pos.setValue(position[0], position[1], position[2]);
  352. body.m_quat.setValue(orientation[0], orientation[1], orientation[2], orientation[3]);
  353. body.m_restituitionCoeff = 0.f;
  354. m_data->m_rigidBodies.push_back(body);
  355. if (collidableIndex >= 0)
  356. {
  357. b3Aabb& worldAabb = m_data->m_aabbWorldSpace.expand();
  358. b3Aabb localAabb = m_data->m_np->getLocalSpaceAabb(collidableIndex);
  359. b3Vector3 localAabbMin = b3MakeVector3(localAabb.m_min[0], localAabb.m_min[1], localAabb.m_min[2]);
  360. b3Vector3 localAabbMax = b3MakeVector3(localAabb.m_max[0], localAabb.m_max[1], localAabb.m_max[2]);
  361. b3Scalar margin = 0.01f;
  362. b3Transform t;
  363. t.setIdentity();
  364. t.setOrigin(b3MakeVector3(position[0], position[1], position[2]));
  365. t.setRotation(b3Quaternion(orientation[0], orientation[1], orientation[2], orientation[3]));
  366. b3TransformAabb(localAabbMin, localAabbMax, margin, t, worldAabb.m_minVec, worldAabb.m_maxVec);
  367. m_data->m_bp->createProxy(worldAabb.m_minVec, worldAabb.m_maxVec, bodyIndex, 0, 1, 1);
  368. // b3Vector3 aabbMin,aabbMax;
  369. // m_data->m_bp->getAabb(bodyIndex,aabbMin,aabbMax);
  370. }
  371. else
  372. {
  373. b3Error("registerPhysicsInstance using invalid collidableIndex\n");
  374. }
  375. return bodyIndex;
  376. }
  377. const struct b3RigidBodyData* b3CpuRigidBodyPipeline::getBodyBuffer() const
  378. {
  379. return m_data->m_rigidBodies.size() ? &m_data->m_rigidBodies[0] : 0;
  380. }
  381. int b3CpuRigidBodyPipeline::getNumBodies() const
  382. {
  383. return m_data->m_rigidBodies.size();
  384. }