btReducedDeformableBody.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792
  1. #include "btReducedDeformableBody.h"
  2. #include "../btSoftBodyInternals.h"
  3. #include "btReducedDeformableBodyHelpers.h"
  4. #include "LinearMath/btTransformUtil.h"
  5. #include <iostream>
  6. #include <fstream>
  7. btReducedDeformableBody::btReducedDeformableBody(btSoftBodyWorldInfo* worldInfo, int node_count, const btVector3* x, const btScalar* m)
  8. : btSoftBody(worldInfo, node_count, x, m), m_rigidOnly(false)
  9. {
  10. // reduced deformable
  11. m_reducedModel = true;
  12. m_nReduced = 0;
  13. m_nFull = 0;
  14. m_nodeIndexOffset = 0;
  15. m_transform_lock = false;
  16. m_ksScale = 1.0;
  17. m_rhoScale = 1.0;
  18. // rigid motion
  19. m_linearVelocity.setZero();
  20. m_angularVelocity.setZero();
  21. m_internalDeltaLinearVelocity.setZero();
  22. m_internalDeltaAngularVelocity.setZero();
  23. m_angularVelocityFromReduced.setZero();
  24. m_internalDeltaAngularVelocityFromReduced.setZero();
  25. m_angularFactor.setValue(1, 1, 1);
  26. m_linearFactor.setValue(1, 1, 1);
  27. // m_invInertiaLocal.setValue(1, 1, 1);
  28. m_invInertiaLocal.setIdentity();
  29. m_mass = 0.0;
  30. m_inverseMass = 0.0;
  31. m_linearDamping = 0;
  32. m_angularDamping = 0;
  33. // Rayleigh damping
  34. m_dampingAlpha = 0;
  35. m_dampingBeta = 0;
  36. m_rigidTransformWorld.setIdentity();
  37. }
  38. void btReducedDeformableBody::setReducedModes(int num_modes, int full_size)
  39. {
  40. m_nReduced = num_modes;
  41. m_nFull = full_size;
  42. m_reducedDofs.resize(m_nReduced, 0);
  43. m_reducedDofsBuffer.resize(m_nReduced, 0);
  44. m_reducedVelocity.resize(m_nReduced, 0);
  45. m_reducedVelocityBuffer.resize(m_nReduced, 0);
  46. m_reducedForceElastic.resize(m_nReduced, 0);
  47. m_reducedForceDamping.resize(m_nReduced, 0);
  48. m_reducedForceExternal.resize(m_nReduced, 0);
  49. m_internalDeltaReducedVelocity.resize(m_nReduced, 0);
  50. m_nodalMass.resize(full_size, 0);
  51. m_localMomentArm.resize(m_nFull);
  52. }
  53. void btReducedDeformableBody::setMassProps(const tDenseArray& mass_array)
  54. {
  55. btScalar total_mass = 0;
  56. btVector3 CoM(0, 0, 0);
  57. for (int i = 0; i < m_nFull; ++i)
  58. {
  59. m_nodalMass[i] = m_rhoScale * mass_array[i];
  60. m_nodes[i].m_im = mass_array[i] > 0 ? 1.0 / (m_rhoScale * mass_array[i]) : 0;
  61. total_mass += m_rhoScale * mass_array[i];
  62. CoM += m_nodalMass[i] * m_nodes[i].m_x;
  63. }
  64. // total rigid body mass
  65. m_mass = total_mass;
  66. m_inverseMass = total_mass > 0 ? 1.0 / total_mass : 0;
  67. // original CoM
  68. m_initialCoM = CoM / total_mass;
  69. }
  70. void btReducedDeformableBody::setInertiaProps()
  71. {
  72. // make sure the initial CoM is at the origin (0,0,0)
  73. // for (int i = 0; i < m_nFull; ++i)
  74. // {
  75. // m_nodes[i].m_x -= m_initialCoM;
  76. // }
  77. // m_initialCoM.setZero();
  78. m_rigidTransformWorld.setOrigin(m_initialCoM);
  79. m_interpolationWorldTransform = m_rigidTransformWorld;
  80. updateLocalInertiaTensorFromNodes();
  81. // update world inertia tensor
  82. btMatrix3x3 rotation;
  83. rotation.setIdentity();
  84. updateInitialInertiaTensor(rotation);
  85. updateInertiaTensor();
  86. m_interpolateInvInertiaTensorWorld = m_invInertiaTensorWorld;
  87. }
  88. void btReducedDeformableBody::setRigidVelocity(const btVector3& v)
  89. {
  90. m_linearVelocity = v;
  91. }
  92. void btReducedDeformableBody::setRigidAngularVelocity(const btVector3& omega)
  93. {
  94. m_angularVelocity = omega;
  95. }
  96. void btReducedDeformableBody::setStiffnessScale(const btScalar ks)
  97. {
  98. m_ksScale = ks;
  99. }
  100. void btReducedDeformableBody::setMassScale(const btScalar rho)
  101. {
  102. m_rhoScale = rho;
  103. }
  104. void btReducedDeformableBody::setFixedNodes(const int n_node)
  105. {
  106. m_fixedNodes.push_back(n_node);
  107. m_nodes[n_node].m_im = 0; // set inverse mass to be zero for the constraint solver.
  108. }
  109. void btReducedDeformableBody::setDamping(const btScalar alpha, const btScalar beta)
  110. {
  111. m_dampingAlpha = alpha;
  112. m_dampingBeta = beta;
  113. }
  114. void btReducedDeformableBody::internalInitialization()
  115. {
  116. // zeroing
  117. endOfTimeStepZeroing();
  118. // initialize rest position
  119. updateRestNodalPositions();
  120. // initialize local nodal moment arm form the CoM
  121. updateLocalMomentArm();
  122. // initialize projection matrix
  123. updateExternalForceProjectMatrix(false);
  124. }
  125. void btReducedDeformableBody::updateLocalMomentArm()
  126. {
  127. TVStack delta_x;
  128. delta_x.resize(m_nFull);
  129. for (int i = 0; i < m_nFull; ++i)
  130. {
  131. for (int k = 0; k < 3; ++k)
  132. {
  133. // compute displacement
  134. delta_x[i][k] = 0;
  135. for (int j = 0; j < m_nReduced; ++j)
  136. {
  137. delta_x[i][k] += m_modes[j][3 * i + k] * m_reducedDofs[j];
  138. }
  139. }
  140. // get new moment arm Sq + x0
  141. m_localMomentArm[i] = m_x0[i] - m_initialCoM + delta_x[i];
  142. }
  143. }
  144. void btReducedDeformableBody::updateExternalForceProjectMatrix(bool initialized)
  145. {
  146. // if not initialized, need to compute both P_A and Cq
  147. // otherwise, only need to udpate Cq
  148. if (!initialized)
  149. {
  150. // resize
  151. m_projPA.resize(m_nReduced);
  152. m_projCq.resize(m_nReduced);
  153. m_STP.resize(m_nReduced);
  154. m_MrInvSTP.resize(m_nReduced);
  155. // P_A
  156. for (int r = 0; r < m_nReduced; ++r)
  157. {
  158. m_projPA[r].resize(3 * m_nFull, 0);
  159. for (int i = 0; i < m_nFull; ++i)
  160. {
  161. btMatrix3x3 mass_scaled_i = Diagonal(1) - Diagonal(m_nodalMass[i] / m_mass);
  162. btVector3 s_ri(m_modes[r][3 * i], m_modes[r][3 * i + 1], m_modes[r][3 * i + 2]);
  163. btVector3 prod_i = mass_scaled_i * s_ri;
  164. for (int k = 0; k < 3; ++k)
  165. m_projPA[r][3 * i + k] = prod_i[k];
  166. // btScalar ratio = m_nodalMass[i] / m_mass;
  167. // m_projPA[r] += btVector3(- m_modes[r][3 * i] * ratio,
  168. // - m_modes[r][3 * i + 1] * ratio,
  169. // - m_modes[r][3 * i + 2] * ratio);
  170. }
  171. }
  172. }
  173. // C(q) is updated once per position update
  174. for (int r = 0; r < m_nReduced; ++r)
  175. {
  176. m_projCq[r].resize(3 * m_nFull, 0);
  177. for (int i = 0; i < m_nFull; ++i)
  178. {
  179. btMatrix3x3 r_star = Cross(m_localMomentArm[i]);
  180. btVector3 s_ri(m_modes[r][3 * i], m_modes[r][3 * i + 1], m_modes[r][3 * i + 2]);
  181. btVector3 prod_i = r_star * m_invInertiaTensorWorld * r_star * s_ri;
  182. for (int k = 0; k < 3; ++k)
  183. m_projCq[r][3 * i + k] = m_nodalMass[i] * prod_i[k];
  184. // btVector3 si(m_modes[r][3 * i], m_modes[r][3 * i + 1], m_modes[r][3 * i + 2]);
  185. // m_projCq[r] += m_nodalMass[i] * si.cross(m_localMomentArm[i]);
  186. }
  187. }
  188. }
  189. void btReducedDeformableBody::endOfTimeStepZeroing()
  190. {
  191. for (int i = 0; i < m_nReduced; ++i)
  192. {
  193. m_reducedForceElastic[i] = 0;
  194. m_reducedForceDamping[i] = 0;
  195. m_reducedForceExternal[i] = 0;
  196. m_internalDeltaReducedVelocity[i] = 0;
  197. m_reducedDofsBuffer[i] = m_reducedDofs[i];
  198. m_reducedVelocityBuffer[i] = m_reducedVelocity[i];
  199. }
  200. // std::cout << "zeroed!\n";
  201. }
  202. void btReducedDeformableBody::applyInternalVelocityChanges()
  203. {
  204. m_linearVelocity += m_internalDeltaLinearVelocity;
  205. m_angularVelocity += m_internalDeltaAngularVelocity;
  206. m_internalDeltaLinearVelocity.setZero();
  207. m_internalDeltaAngularVelocity.setZero();
  208. for (int r = 0; r < m_nReduced; ++r)
  209. {
  210. m_reducedVelocity[r] += m_internalDeltaReducedVelocity[r];
  211. m_internalDeltaReducedVelocity[r] = 0;
  212. }
  213. }
  214. void btReducedDeformableBody::predictIntegratedTransform(btScalar dt, btTransform& predictedTransform)
  215. {
  216. btTransformUtil::integrateTransform(m_rigidTransformWorld, m_linearVelocity, m_angularVelocity, dt, predictedTransform);
  217. }
  218. void btReducedDeformableBody::updateReducedDofs(btScalar solverdt)
  219. {
  220. for (int r = 0; r < m_nReduced; ++r)
  221. {
  222. m_reducedDofs[r] = m_reducedDofsBuffer[r] + solverdt * m_reducedVelocity[r];
  223. }
  224. }
  225. void btReducedDeformableBody::mapToFullPosition(const btTransform& ref_trans)
  226. {
  227. btVector3 origin = ref_trans.getOrigin();
  228. btMatrix3x3 rotation = ref_trans.getBasis();
  229. for (int i = 0; i < m_nFull; ++i)
  230. {
  231. m_nodes[i].m_x = rotation * m_localMomentArm[i] + origin;
  232. m_nodes[i].m_q = m_nodes[i].m_x;
  233. }
  234. }
  235. void btReducedDeformableBody::updateReducedVelocity(btScalar solverdt)
  236. {
  237. // update reduced velocity
  238. for (int r = 0; r < m_nReduced; ++r)
  239. {
  240. // the reduced mass is always identity!
  241. btScalar delta_v = 0;
  242. delta_v = solverdt * (m_reducedForceElastic[r] + m_reducedForceDamping[r]);
  243. // delta_v = solverdt * (m_reducedForceElastic[r] + m_reducedForceDamping[r] + m_reducedForceExternal[r]);
  244. m_reducedVelocity[r] = m_reducedVelocityBuffer[r] + delta_v;
  245. }
  246. }
  247. void btReducedDeformableBody::mapToFullVelocity(const btTransform& ref_trans)
  248. {
  249. // compute the reduced contribution to the angular velocity
  250. // btVector3 sum_linear(0, 0, 0);
  251. // btVector3 sum_angular(0, 0, 0);
  252. // m_linearVelocityFromReduced.setZero();
  253. // m_angularVelocityFromReduced.setZero();
  254. // for (int i = 0; i < m_nFull; ++i)
  255. // {
  256. // btVector3 r_com = ref_trans.getBasis() * m_localMomentArm[i];
  257. // btMatrix3x3 r_star = Cross(r_com);
  258. // btVector3 v_from_reduced(0, 0, 0);
  259. // for (int k = 0; k < 3; ++k)
  260. // {
  261. // for (int r = 0; r < m_nReduced; ++r)
  262. // {
  263. // v_from_reduced[k] += m_modes[r][3 * i + k] * m_reducedVelocity[r];
  264. // }
  265. // }
  266. // btVector3 delta_linear = m_nodalMass[i] * v_from_reduced;
  267. // btVector3 delta_angular = m_nodalMass[i] * (r_star * ref_trans.getBasis() * v_from_reduced);
  268. // sum_linear += delta_linear;
  269. // sum_angular += delta_angular;
  270. // // std::cout << "delta_linear: " << delta_linear[0] << "\t" << delta_linear[1] << "\t" << delta_linear[2] << "\n";
  271. // // std::cout << "delta_angular: " << delta_angular[0] << "\t" << delta_angular[1] << "\t" << delta_angular[2] << "\n";
  272. // // std::cout << "sum_linear: " << sum_linear[0] << "\t" << sum_linear[1] << "\t" << sum_linear[2] << "\n";
  273. // // std::cout << "sum_angular: " << sum_angular[0] << "\t" << sum_angular[1] << "\t" << sum_angular[2] << "\n";
  274. // }
  275. // m_linearVelocityFromReduced = 1.0 / m_mass * (ref_trans.getBasis() * sum_linear);
  276. // m_angularVelocityFromReduced = m_interpolateInvInertiaTensorWorld * sum_angular;
  277. // m_linearVelocity -= m_linearVelocityFromReduced;
  278. // m_angularVelocity -= m_angularVelocityFromReduced;
  279. for (int i = 0; i < m_nFull; ++i)
  280. {
  281. m_nodes[i].m_v = computeNodeFullVelocity(ref_trans, i);
  282. }
  283. }
  284. const btVector3 btReducedDeformableBody::computeTotalAngularMomentum() const
  285. {
  286. btVector3 L_rigid = m_invInertiaTensorWorld.inverse() * m_angularVelocity;
  287. btVector3 L_reduced(0, 0, 0);
  288. btMatrix3x3 omega_prime_star = Cross(m_angularVelocityFromReduced);
  289. for (int i = 0; i < m_nFull; ++i)
  290. {
  291. btVector3 r_com = m_rigidTransformWorld.getBasis() * m_localMomentArm[i];
  292. btMatrix3x3 r_star = Cross(r_com);
  293. btVector3 v_from_reduced(0, 0, 0);
  294. for (int k = 0; k < 3; ++k)
  295. {
  296. for (int r = 0; r < m_nReduced; ++r)
  297. {
  298. v_from_reduced[k] += m_modes[r][3 * i + k] * m_reducedVelocity[r];
  299. }
  300. }
  301. L_reduced += m_nodalMass[i] * (r_star * (m_rigidTransformWorld.getBasis() * v_from_reduced - omega_prime_star * r_com));
  302. // L_reduced += m_nodalMass[i] * (r_star * (m_rigidTransformWorld.getBasis() * v_from_reduced));
  303. }
  304. return L_rigid + L_reduced;
  305. }
  306. const btVector3 btReducedDeformableBody::computeNodeFullVelocity(const btTransform& ref_trans, int n_node) const
  307. {
  308. btVector3 v_from_reduced(0, 0, 0);
  309. btVector3 r_com = ref_trans.getBasis() * m_localMomentArm[n_node];
  310. // compute velocity contributed by the reduced velocity
  311. for (int k = 0; k < 3; ++k)
  312. {
  313. for (int r = 0; r < m_nReduced; ++r)
  314. {
  315. v_from_reduced[k] += m_modes[r][3 * n_node + k] * m_reducedVelocity[r];
  316. }
  317. }
  318. // get new velocity
  319. btVector3 vel = m_angularVelocity.cross(r_com) +
  320. ref_trans.getBasis() * v_from_reduced +
  321. m_linearVelocity;
  322. return vel;
  323. }
  324. const btVector3 btReducedDeformableBody::internalComputeNodeDeltaVelocity(const btTransform& ref_trans, int n_node) const
  325. {
  326. btVector3 deltaV_from_reduced(0, 0, 0);
  327. btVector3 r_com = ref_trans.getBasis() * m_localMomentArm[n_node];
  328. // compute velocity contributed by the reduced velocity
  329. for (int k = 0; k < 3; ++k)
  330. {
  331. for (int r = 0; r < m_nReduced; ++r)
  332. {
  333. deltaV_from_reduced[k] += m_modes[r][3 * n_node + k] * m_internalDeltaReducedVelocity[r];
  334. }
  335. }
  336. // get delta velocity
  337. btVector3 deltaV = m_internalDeltaAngularVelocity.cross(r_com) +
  338. ref_trans.getBasis() * deltaV_from_reduced +
  339. m_internalDeltaLinearVelocity;
  340. return deltaV;
  341. }
  342. void btReducedDeformableBody::proceedToTransform(btScalar dt, bool end_of_time_step)
  343. {
  344. btTransformUtil::integrateTransform(m_rigidTransformWorld, m_linearVelocity, m_angularVelocity, dt, m_interpolationWorldTransform);
  345. updateInertiaTensor();
  346. // m_interpolateInvInertiaTensorWorld = m_interpolationWorldTransform.getBasis().scaled(m_invInertiaLocal) * m_interpolationWorldTransform.getBasis().transpose();
  347. m_rigidTransformWorld = m_interpolationWorldTransform;
  348. m_invInertiaTensorWorld = m_interpolateInvInertiaTensorWorld;
  349. }
  350. void btReducedDeformableBody::transformTo(const btTransform& trs)
  351. {
  352. btTransform current_transform = getRigidTransform();
  353. btTransform new_transform(trs.getBasis() * current_transform.getBasis().transpose(),
  354. trs.getOrigin() - current_transform.getOrigin());
  355. transform(new_transform);
  356. }
  357. void btReducedDeformableBody::transform(const btTransform& trs)
  358. {
  359. m_transform_lock = true;
  360. // transform mesh
  361. {
  362. const btScalar margin = getCollisionShape()->getMargin();
  363. ATTRIBUTE_ALIGNED16(btDbvtVolume)
  364. vol;
  365. btVector3 CoM = m_rigidTransformWorld.getOrigin();
  366. btVector3 translation = trs.getOrigin();
  367. btMatrix3x3 rotation = trs.getBasis();
  368. for (int i = 0; i < m_nodes.size(); ++i)
  369. {
  370. Node& n = m_nodes[i];
  371. n.m_x = rotation * (n.m_x - CoM) + CoM + translation;
  372. n.m_q = rotation * (n.m_q - CoM) + CoM + translation;
  373. n.m_n = rotation * n.m_n;
  374. vol = btDbvtVolume::FromCR(n.m_x, margin);
  375. m_ndbvt.update(n.m_leaf, vol);
  376. }
  377. updateNormals();
  378. updateBounds();
  379. updateConstants();
  380. }
  381. // update modes
  382. updateModesByRotation(trs.getBasis());
  383. // update inertia tensor
  384. updateInitialInertiaTensor(trs.getBasis());
  385. updateInertiaTensor();
  386. m_interpolateInvInertiaTensorWorld = m_invInertiaTensorWorld;
  387. // update rigid frame (No need to update the rotation. Nodes have already been updated.)
  388. m_rigidTransformWorld.setOrigin(m_initialCoM + trs.getOrigin());
  389. m_interpolationWorldTransform = m_rigidTransformWorld;
  390. m_initialCoM = m_rigidTransformWorld.getOrigin();
  391. internalInitialization();
  392. }
  393. void btReducedDeformableBody::scale(const btVector3& scl)
  394. {
  395. // Scaling the mesh after transform is applied is not allowed
  396. btAssert(!m_transform_lock);
  397. // scale the mesh
  398. {
  399. const btScalar margin = getCollisionShape()->getMargin();
  400. ATTRIBUTE_ALIGNED16(btDbvtVolume)
  401. vol;
  402. btVector3 CoM = m_rigidTransformWorld.getOrigin();
  403. for (int i = 0; i < m_nodes.size(); ++i)
  404. {
  405. Node& n = m_nodes[i];
  406. n.m_x = (n.m_x - CoM) * scl + CoM;
  407. n.m_q = (n.m_q - CoM) * scl + CoM;
  408. vol = btDbvtVolume::FromCR(n.m_x, margin);
  409. m_ndbvt.update(n.m_leaf, vol);
  410. }
  411. updateNormals();
  412. updateBounds();
  413. updateConstants();
  414. initializeDmInverse();
  415. }
  416. // update inertia tensor
  417. updateLocalInertiaTensorFromNodes();
  418. btMatrix3x3 id;
  419. id.setIdentity();
  420. updateInitialInertiaTensor(id); // there is no rotation, but the local inertia tensor has changed
  421. updateInertiaTensor();
  422. m_interpolateInvInertiaTensorWorld = m_invInertiaTensorWorld;
  423. internalInitialization();
  424. }
  425. void btReducedDeformableBody::setTotalMass(btScalar mass, bool fromfaces)
  426. {
  427. // Changing the total mass after transform is applied is not allowed
  428. btAssert(!m_transform_lock);
  429. btScalar scale_ratio = mass / m_mass;
  430. // update nodal mass
  431. for (int i = 0; i < m_nFull; ++i)
  432. {
  433. m_nodalMass[i] *= scale_ratio;
  434. }
  435. m_mass = mass;
  436. m_inverseMass = mass > 0 ? 1.0 / mass : 0;
  437. // update inertia tensors
  438. updateLocalInertiaTensorFromNodes();
  439. btMatrix3x3 id;
  440. id.setIdentity();
  441. updateInitialInertiaTensor(id); // there is no rotation, but the local inertia tensor has changed
  442. updateInertiaTensor();
  443. m_interpolateInvInertiaTensorWorld = m_invInertiaTensorWorld;
  444. internalInitialization();
  445. }
  446. void btReducedDeformableBody::updateRestNodalPositions()
  447. {
  448. // update reset nodal position
  449. m_x0.resize(m_nFull);
  450. for (int i = 0; i < m_nFull; ++i)
  451. {
  452. m_x0[i] = m_nodes[i].m_x;
  453. }
  454. }
  455. // reference notes:
  456. // https://ocw.mit.edu/courses/aeronautics-and-astronautics/16-07-dynamics-fall-2009/lecture-notes/MIT16_07F09_Lec26.pdf
  457. void btReducedDeformableBody::updateLocalInertiaTensorFromNodes()
  458. {
  459. btMatrix3x3 inertia_tensor;
  460. inertia_tensor.setZero();
  461. for (int p = 0; p < m_nFull; ++p)
  462. {
  463. btMatrix3x3 particle_inertia;
  464. particle_inertia.setZero();
  465. btVector3 r = m_nodes[p].m_x - m_initialCoM;
  466. particle_inertia[0][0] = m_nodalMass[p] * (r[1] * r[1] + r[2] * r[2]);
  467. particle_inertia[1][1] = m_nodalMass[p] * (r[0] * r[0] + r[2] * r[2]);
  468. particle_inertia[2][2] = m_nodalMass[p] * (r[0] * r[0] + r[1] * r[1]);
  469. particle_inertia[0][1] = - m_nodalMass[p] * (r[0] * r[1]);
  470. particle_inertia[0][2] = - m_nodalMass[p] * (r[0] * r[2]);
  471. particle_inertia[1][2] = - m_nodalMass[p] * (r[1] * r[2]);
  472. particle_inertia[1][0] = particle_inertia[0][1];
  473. particle_inertia[2][0] = particle_inertia[0][2];
  474. particle_inertia[2][1] = particle_inertia[1][2];
  475. inertia_tensor += particle_inertia;
  476. }
  477. m_invInertiaLocal = inertia_tensor.inverse();
  478. }
  479. void btReducedDeformableBody::updateInitialInertiaTensor(const btMatrix3x3& rotation)
  480. {
  481. // m_invInertiaTensorWorldInitial = rotation.scaled(m_invInertiaLocal) * rotation.transpose();
  482. m_invInertiaTensorWorldInitial = rotation * m_invInertiaLocal * rotation.transpose();
  483. }
  484. void btReducedDeformableBody::updateModesByRotation(const btMatrix3x3& rotation)
  485. {
  486. for (int r = 0; r < m_nReduced; ++r)
  487. {
  488. for (int i = 0; i < m_nFull; ++i)
  489. {
  490. btVector3 nodal_disp(m_modes[r][3 * i], m_modes[r][3 * i + 1], m_modes[r][3 * i + 2]);
  491. nodal_disp = rotation * nodal_disp;
  492. for (int k = 0; k < 3; ++k)
  493. {
  494. m_modes[r][3 * i + k] = nodal_disp[k];
  495. }
  496. }
  497. }
  498. }
  499. void btReducedDeformableBody::updateInertiaTensor()
  500. {
  501. m_invInertiaTensorWorld = m_rigidTransformWorld.getBasis() * m_invInertiaTensorWorldInitial * m_rigidTransformWorld.getBasis().transpose();
  502. }
  503. void btReducedDeformableBody::applyDamping(btScalar timeStep)
  504. {
  505. m_linearVelocity *= btScalar(1) - m_linearDamping;
  506. m_angularDamping *= btScalar(1) - m_angularDamping;
  507. }
  508. void btReducedDeformableBody::applyCentralImpulse(const btVector3& impulse)
  509. {
  510. m_linearVelocity += impulse * m_linearFactor * m_inverseMass;
  511. #if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
  512. clampVelocity(m_linearVelocity);
  513. #endif
  514. }
  515. void btReducedDeformableBody::applyTorqueImpulse(const btVector3& torque)
  516. {
  517. m_angularVelocity += m_interpolateInvInertiaTensorWorld * torque * m_angularFactor;
  518. #if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
  519. clampVelocity(m_angularVelocity);
  520. #endif
  521. }
  522. void btReducedDeformableBody::internalApplyRigidImpulse(const btVector3& impulse, const btVector3& rel_pos)
  523. {
  524. if (m_inverseMass == btScalar(0.))
  525. {
  526. std::cout << "something went wrong...probably didn't initialize?\n";
  527. btAssert(false);
  528. }
  529. // delta linear velocity
  530. m_internalDeltaLinearVelocity += impulse * m_linearFactor * m_inverseMass;
  531. // delta angular velocity
  532. btVector3 torque = rel_pos.cross(impulse * m_linearFactor);
  533. m_internalDeltaAngularVelocity += m_interpolateInvInertiaTensorWorld * torque * m_angularFactor;
  534. }
  535. btVector3 btReducedDeformableBody::getRelativePos(int n_node)
  536. {
  537. btMatrix3x3 rotation = m_interpolationWorldTransform.getBasis();
  538. btVector3 ri = rotation * m_localMomentArm[n_node];
  539. return ri;
  540. }
  541. btMatrix3x3 btReducedDeformableBody::getImpulseFactor(int n_node)
  542. {
  543. // relative position
  544. btMatrix3x3 rotation = m_interpolationWorldTransform.getBasis();
  545. btVector3 ri = rotation * m_localMomentArm[n_node];
  546. btMatrix3x3 ri_skew = Cross(ri);
  547. // calculate impulse factor
  548. // rigid part
  549. btScalar inv_mass = m_nodalMass[n_node] > btScalar(0) ? btScalar(1) / m_mass : btScalar(0);
  550. btMatrix3x3 K1 = Diagonal(inv_mass);
  551. K1 -= ri_skew * m_interpolateInvInertiaTensorWorld * ri_skew;
  552. // reduced deformable part
  553. btMatrix3x3 SA;
  554. SA.setZero();
  555. for (int i = 0; i < 3; ++i)
  556. {
  557. for (int j = 0; j < 3; ++j)
  558. {
  559. for (int r = 0; r < m_nReduced; ++r)
  560. {
  561. SA[i][j] += m_modes[r][3 * n_node + i] * (m_projPA[r][3 * n_node + j] + m_projCq[r][3 * n_node + j]);
  562. }
  563. }
  564. }
  565. btMatrix3x3 RSARinv = rotation * SA * rotation.transpose();
  566. TVStack omega_helper; // Sum_i m_i r*_i R S_i
  567. omega_helper.resize(m_nReduced);
  568. for (int r = 0; r < m_nReduced; ++r)
  569. {
  570. omega_helper[r].setZero();
  571. for (int i = 0; i < m_nFull; ++i)
  572. {
  573. btMatrix3x3 mi_rstar_i = rotation * Cross(m_localMomentArm[i]) * m_nodalMass[i];
  574. btVector3 s_ri(m_modes[r][3 * i], m_modes[r][3 * i + 1], m_modes[r][3 * i + 2]);
  575. omega_helper[r] += mi_rstar_i * rotation * s_ri;
  576. }
  577. }
  578. btMatrix3x3 sum_multiply_A;
  579. sum_multiply_A.setZero();
  580. for (int i = 0; i < 3; ++i)
  581. {
  582. for (int j = 0; j < 3; ++j)
  583. {
  584. for (int r = 0; r < m_nReduced; ++r)
  585. {
  586. sum_multiply_A[i][j] += omega_helper[r][i] * (m_projPA[r][3 * n_node + j] + m_projCq[r][3 * n_node + j]);
  587. }
  588. }
  589. }
  590. btMatrix3x3 K2 = RSARinv + ri_skew * m_interpolateInvInertiaTensorWorld * sum_multiply_A * rotation.transpose();
  591. return m_rigidOnly ? K1 : K1 + K2;
  592. }
  593. void btReducedDeformableBody::internalApplyFullSpaceImpulse(const btVector3& impulse, const btVector3& rel_pos, int n_node, btScalar dt)
  594. {
  595. if (!m_rigidOnly)
  596. {
  597. // apply impulse force
  598. applyFullSpaceNodalForce(impulse / dt, n_node);
  599. // update delta damping force
  600. tDenseArray reduced_vel_tmp;
  601. reduced_vel_tmp.resize(m_nReduced);
  602. for (int r = 0; r < m_nReduced; ++r)
  603. {
  604. reduced_vel_tmp[r] = m_reducedVelocity[r] + m_internalDeltaReducedVelocity[r];
  605. }
  606. applyReducedDampingForce(reduced_vel_tmp);
  607. // applyReducedDampingForce(m_internalDeltaReducedVelocity);
  608. // delta reduced velocity
  609. for (int r = 0; r < m_nReduced; ++r)
  610. {
  611. // The reduced mass is always identity!
  612. m_internalDeltaReducedVelocity[r] += dt * (m_reducedForceDamping[r] + m_reducedForceExternal[r]);
  613. }
  614. }
  615. internalApplyRigidImpulse(impulse, rel_pos);
  616. }
  617. void btReducedDeformableBody::applyFullSpaceNodalForce(const btVector3& f_ext, int n_node)
  618. {
  619. // f_local = R^-1 * f_ext //TODO: interpoalted transfrom
  620. // btVector3 f_local = m_rigidTransformWorld.getBasis().transpose() * f_ext;
  621. btVector3 f_local = m_interpolationWorldTransform.getBasis().transpose() * f_ext;
  622. // f_ext_r = [S^T * P]_{n_node} * f_local
  623. tDenseArray f_ext_r;
  624. f_ext_r.resize(m_nReduced, 0);
  625. for (int r = 0; r < m_nReduced; ++r)
  626. {
  627. m_reducedForceExternal[r] = 0;
  628. for (int k = 0; k < 3; ++k)
  629. {
  630. f_ext_r[r] += (m_projPA[r][3 * n_node + k] + m_projCq[r][3 * n_node + k]) * f_local[k];
  631. }
  632. m_reducedForceExternal[r] += f_ext_r[r];
  633. }
  634. }
  635. void btReducedDeformableBody::applyRigidGravity(const btVector3& gravity, btScalar dt)
  636. {
  637. // update rigid frame velocity
  638. m_linearVelocity += dt * gravity;
  639. }
  640. void btReducedDeformableBody::applyReducedElasticForce(const tDenseArray& reduce_dofs)
  641. {
  642. for (int r = 0; r < m_nReduced; ++r)
  643. {
  644. m_reducedForceElastic[r] = - m_ksScale * m_Kr[r] * reduce_dofs[r];
  645. }
  646. }
  647. void btReducedDeformableBody::applyReducedDampingForce(const tDenseArray& reduce_vel)
  648. {
  649. for (int r = 0; r < m_nReduced; ++r)
  650. {
  651. m_reducedForceDamping[r] = - m_dampingBeta * m_ksScale * m_Kr[r] * reduce_vel[r];
  652. }
  653. }
  654. btScalar btReducedDeformableBody::getTotalMass() const
  655. {
  656. return m_mass;
  657. }
  658. btTransform& btReducedDeformableBody::getRigidTransform()
  659. {
  660. return m_rigidTransformWorld;
  661. }
  662. const btVector3& btReducedDeformableBody::getLinearVelocity() const
  663. {
  664. return m_linearVelocity;
  665. }
  666. const btVector3& btReducedDeformableBody::getAngularVelocity() const
  667. {
  668. return m_angularVelocity;
  669. }
  670. void btReducedDeformableBody::disableReducedModes(const bool rigid_only)
  671. {
  672. m_rigidOnly = rigid_only;
  673. }
  674. bool btReducedDeformableBody::isReducedModesOFF() const
  675. {
  676. return m_rigidOnly;
  677. }