joints_2d_sw.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575
  1. /*************************************************************************/
  2. /* joints_2d_sw.cpp */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* http://www.godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
  9. /* */
  10. /* Permission is hereby granted, free of charge, to any person obtaining */
  11. /* a copy of this software and associated documentation files (the */
  12. /* "Software"), to deal in the Software without restriction, including */
  13. /* without limitation the rights to use, copy, modify, merge, publish, */
  14. /* distribute, sublicense, and/or sell copies of the Software, and to */
  15. /* permit persons to whom the Software is furnished to do so, subject to */
  16. /* the following conditions: */
  17. /* */
  18. /* The above copyright notice and this permission notice shall be */
  19. /* included in all copies or substantial portions of the Software. */
  20. /* */
  21. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  22. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  23. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
  24. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  25. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  26. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  27. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  28. /*************************************************************************/
  29. #include "joints_2d_sw.h"
  30. #include "space_2d_sw.h"
  31. //based on chipmunk joint constraints
  32. /* Copyright (c) 2007 Scott Lembcke
  33. *
  34. * Permission is hereby granted, free of charge, to any person obtaining a copy
  35. * of this software and associated documentation files (the "Software"), to deal
  36. * in the Software without restriction, including without limitation the rights
  37. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  38. * copies of the Software, and to permit persons to whom the Software is
  39. * furnished to do so, subject to the following conditions:
  40. *
  41. * The above copyright notice and this permission notice shall be included in
  42. * all copies or substantial portions of the Software.
  43. *
  44. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  45. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  46. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  47. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  48. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  49. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  50. * SOFTWARE.
  51. */
  52. static inline real_t k_scalar(Body2DSW *a,Body2DSW *b,const Vector2& rA, const Vector2& rB, const Vector2& n) {
  53. real_t value=0;
  54. {
  55. value+=a->get_inv_mass();
  56. real_t rcn = rA.cross(n);
  57. value+=a->get_inv_inertia() * rcn * rcn;
  58. }
  59. if (b) {
  60. value+=b->get_inv_mass();
  61. real_t rcn = rB.cross(n);
  62. value+=b->get_inv_inertia() * rcn * rcn;
  63. }
  64. return value;
  65. }
  66. static inline Vector2
  67. relative_velocity(Body2DSW *a, Body2DSW *b, Vector2 rA, Vector2 rB){
  68. Vector2 sum = a->get_linear_velocity() -rA.tangent() * a->get_angular_velocity();
  69. if (b)
  70. return (b->get_linear_velocity() -rB.tangent() * b->get_angular_velocity()) - sum;
  71. else
  72. return -sum;
  73. }
  74. static inline real_t
  75. normal_relative_velocity(Body2DSW *a, Body2DSW *b, Vector2 rA, Vector2 rB, Vector2 n){
  76. return relative_velocity(a, b, rA, rB).dot(n);
  77. }
  78. #if 0
  79. bool PinJoint2DSW::setup(float p_step) {
  80. Space2DSW *space = A->get_space();
  81. ERR_FAIL_COND_V(!space,false;)
  82. rA = A->get_transform().basis_xform(anchor_A);
  83. rB = B?B->get_transform().basis_xform(anchor_B):anchor_B;
  84. Vector2 gA = A->get_transform().get_origin();
  85. Vector2 gB = B?B->get_transform().get_origin():Vector2();
  86. Vector2 delta = gB - gA;
  87. delta = (delta+rB) -rA;
  88. real_t jdist = delta.length();
  89. correct=false;
  90. if (jdist==0)
  91. return false; // do not correct
  92. correct=true;
  93. n = delta / jdist;
  94. // calculate mass normal
  95. mass_normal = 1.0f/k_scalar(A, B, rA, rB, n);
  96. // calculate bias velocity
  97. //real_t maxBias = joint->constraint.maxBias;
  98. bias = -(get_bias()==0?space->get_constraint_bias():get_bias())*(1.0/p_step)*(jdist-dist);
  99. bias = CLAMP(bias, -get_max_bias(), +get_max_bias());
  100. // compute max impulse
  101. jn_max = get_max_force() * p_step;
  102. // apply accumulated impulse
  103. Vector2 j = n * jn_acc;
  104. A->apply_impulse(rA,-j);
  105. if (B)
  106. B->apply_impulse(rB,j);
  107. print_line("setup");
  108. return true;
  109. }
  110. void PinJoint2DSW::solve(float p_step){
  111. if (!correct)
  112. return;
  113. Vector2 ln = n;
  114. // compute relative velocity
  115. real_t vrn = normal_relative_velocity(A,B, rA, rB, ln);
  116. // compute normal impulse
  117. real_t jn = (bias - vrn)*mass_normal;
  118. real_t jnOld = jn_acc;
  119. jn_acc = CLAMP(jnOld + jn,-jn_max,jn_max); //cpfclamp(jnOld + jn, -joint->jnMax, joint->jnMax);
  120. jn = jn_acc - jnOld;
  121. print_line("jn_acc: "+rtos(jn_acc));
  122. Vector2 j = jn*ln;
  123. A->apply_impulse(rA,-j);
  124. if (B)
  125. B->apply_impulse(rB,j);
  126. }
  127. PinJoint2DSW::PinJoint2DSW(const Vector2& p_pos,Body2DSW* p_body_a,Body2DSW* p_body_b) : Joint2DSW(_arr,p_body_b?2:1) {
  128. A=p_body_a;
  129. B=p_body_b;
  130. anchor_A = p_body_a->get_inv_transform().xform(p_pos);
  131. anchor_B = p_body_b?p_body_b->get_inv_transform().xform(p_pos):p_pos;
  132. jn_acc=0;
  133. dist=0;
  134. p_body_a->add_constraint(this,0);
  135. if (p_body_b)
  136. p_body_b->add_constraint(this,1);
  137. }
  138. PinJoint2DSW::~PinJoint2DSW() {
  139. if (A)
  140. A->remove_constraint(this);
  141. if (B)
  142. B->remove_constraint(this);
  143. }
  144. #else
  145. bool PinJoint2DSW::setup(float p_step) {
  146. Space2DSW *space = A->get_space();
  147. ERR_FAIL_COND_V(!space,false;)
  148. rA = A->get_transform().basis_xform(anchor_A);
  149. rB = B?B->get_transform().basis_xform(anchor_B):anchor_B;
  150. #if 0
  151. Vector2 gA = rA+A->get_transform().get_origin();
  152. Vector2 gB = B?rB+B->get_transform().get_origin():rB;
  153. VectorB delta = gB - gA;
  154. real_t jdist = delta.length();
  155. correct=false;
  156. if (jdist==0)
  157. return false; // do not correct
  158. #endif
  159. // deltaV = deltaV0 + K * impulse
  160. // invM = [(1/m1 + 1/m2) * eye(2) - skew(rA) * invI1 * skew(rA) - skew(rB) * invI2 * skew(rB)]
  161. // = [1/m1+1/m2 0 ] + invI1 * [rA.y*rA.y -rA.x*rA.y] + invI2 * [rA.y*rA.y -rA.x*rA.y]
  162. // [ 0 1/m1+1/m2] [-rA.x*rA.y rA.x*rA.x] [-rA.x*rA.y rA.x*rA.x]
  163. real_t B_inv_mass = B?B->get_inv_mass():0.0;
  164. Matrix32 K1;
  165. K1[0].x = A->get_inv_mass() + B_inv_mass; K1[1].x = 0.0f;
  166. K1[0].y = 0.0f; K1[1].y = A->get_inv_mass() + B_inv_mass;
  167. Matrix32 K2;
  168. K2[0].x = A->get_inv_inertia() * rA.y * rA.y; K2[1].x = -A->get_inv_inertia() * rA.x * rA.y;
  169. K2[0].y = -A->get_inv_inertia() * rA.x * rA.y; K2[1].y = A->get_inv_inertia() * rA.x * rA.x;
  170. Matrix32 K;
  171. K[0]= K1[0] + K2[0];
  172. K[1]= K1[1] + K2[1];
  173. if (B) {
  174. Matrix32 K3;
  175. K3[0].x = B->get_inv_inertia() * rB.y * rB.y; K3[1].x = -B->get_inv_inertia() * rB.x * rB.y;
  176. K3[0].y = -B->get_inv_inertia() * rB.x * rB.y; K3[1].y = B->get_inv_inertia() * rB.x * rB.x;
  177. K[0]+=K3[0];
  178. K[1]+=K3[1];
  179. }
  180. K[0].x += softness;
  181. K[1].y += softness;
  182. M = K.affine_inverse();
  183. Vector2 gA = rA+A->get_transform().get_origin();
  184. Vector2 gB = B?rB+B->get_transform().get_origin():rB;
  185. Vector2 delta = gB - gA;
  186. bias = delta*-(get_bias()==0?space->get_constraint_bias():get_bias())*(1.0/p_step);
  187. // apply accumulated impulse
  188. A->apply_impulse(rA,-P);
  189. if (B)
  190. B->apply_impulse(rB,P);
  191. return true;
  192. }
  193. void PinJoint2DSW::solve(float p_step){
  194. // compute relative velocity
  195. Vector2 vA = A->get_linear_velocity() - rA.cross(A->get_angular_velocity());
  196. Vector2 rel_vel;
  197. if (B)
  198. rel_vel = B->get_linear_velocity() - rB.cross(B->get_angular_velocity()) - vA;
  199. else
  200. rel_vel = -vA;
  201. Vector2 impulse = M.basis_xform(bias - rel_vel - Vector2(softness,softness) * P);
  202. A->apply_impulse(rA,-impulse);
  203. if (B)
  204. B->apply_impulse(rB,impulse);
  205. P += impulse;
  206. }
  207. PinJoint2DSW::PinJoint2DSW(const Vector2& p_pos,Body2DSW* p_body_a,Body2DSW* p_body_b) : Joint2DSW(_arr,p_body_b?2:1) {
  208. A=p_body_a;
  209. B=p_body_b;
  210. anchor_A = p_body_a->get_inv_transform().xform(p_pos);
  211. anchor_B = p_body_b?p_body_b->get_inv_transform().xform(p_pos):p_pos;
  212. softness=0;
  213. p_body_a->add_constraint(this,0);
  214. if (p_body_b)
  215. p_body_b->add_constraint(this,1);
  216. }
  217. PinJoint2DSW::~PinJoint2DSW() {
  218. if (A)
  219. A->remove_constraint(this);
  220. if (B)
  221. B->remove_constraint(this);
  222. }
  223. #endif
  224. //////////////////////////////////////////////
  225. //////////////////////////////////////////////
  226. //////////////////////////////////////////////
  227. static inline void
  228. k_tensor(Body2DSW *a, Body2DSW *b, Vector2 r1, Vector2 r2, Vector2 *k1, Vector2 *k2)
  229. {
  230. // calculate mass matrix
  231. // If I wasn't lazy and wrote a proper matrix class, this wouldn't be so gross...
  232. real_t k11, k12, k21, k22;
  233. real_t m_sum = a->get_inv_mass() + b->get_inv_mass();
  234. // start with I*m_sum
  235. k11 = m_sum; k12 = 0.0f;
  236. k21 = 0.0f; k22 = m_sum;
  237. // add the influence from r1
  238. real_t a_i_inv = a->get_inv_inertia();
  239. real_t r1xsq = r1.x * r1.x * a_i_inv;
  240. real_t r1ysq = r1.y * r1.y * a_i_inv;
  241. real_t r1nxy = -r1.x * r1.y * a_i_inv;
  242. k11 += r1ysq; k12 += r1nxy;
  243. k21 += r1nxy; k22 += r1xsq;
  244. // add the influnce from r2
  245. real_t b_i_inv = b->get_inv_inertia();
  246. real_t r2xsq = r2.x * r2.x * b_i_inv;
  247. real_t r2ysq = r2.y * r2.y * b_i_inv;
  248. real_t r2nxy = -r2.x * r2.y * b_i_inv;
  249. k11 += r2ysq; k12 += r2nxy;
  250. k21 += r2nxy; k22 += r2xsq;
  251. // invert
  252. real_t determinant = k11*k22 - k12*k21;
  253. ERR_FAIL_COND(determinant== 0.0);
  254. real_t det_inv = 1.0f/determinant;
  255. *k1 = Vector2( k22*det_inv, -k12*det_inv);
  256. *k2 = Vector2(-k21*det_inv, k11*det_inv);
  257. }
  258. static _FORCE_INLINE_ Vector2
  259. mult_k(const Vector2& vr, const Vector2 &k1, const Vector2 &k2)
  260. {
  261. return Vector2(vr.dot(k1), vr.dot(k2));
  262. }
  263. bool GrooveJoint2DSW::setup(float p_step) {
  264. // calculate endpoints in worldspace
  265. Vector2 ta = A->get_transform().xform(A_groove_1);
  266. Vector2 tb = A->get_transform().xform(A_groove_2);
  267. Space2DSW *space=A->get_space();
  268. // calculate axis
  269. Vector2 n = -(tb - ta).tangent().normalized();
  270. real_t d = ta.dot(n);
  271. xf_normal = n;
  272. rB = B->get_transform().basis_xform(B_anchor);
  273. // calculate tangential distance along the axis of rB
  274. real_t td = (B->get_transform().get_origin() + rB).cross(n);
  275. // calculate clamping factor and rB
  276. if(td <= ta.cross(n)){
  277. clamp = 1.0f;
  278. rA = ta - A->get_transform().get_origin();
  279. } else if(td >= tb.cross(n)){
  280. clamp = -1.0f;
  281. rA = tb - A->get_transform().get_origin();
  282. } else {
  283. clamp = 0.0f;
  284. //joint->r1 = cpvsub(cpvadd(cpvmult(cpvperp(n), -td), cpvmult(n, d)), a->p);
  285. rA = ((-n.tangent() * -td) + n*d) - A->get_transform().get_origin();
  286. }
  287. // Calculate mass tensor
  288. k_tensor(A, B, rA, rB, &k1, &k2);
  289. // compute max impulse
  290. jn_max = get_max_force() * p_step;
  291. // calculate bias velocity
  292. // cpVect delta = cpvsub(cpvadd(b->p, joint->r2), cpvadd(a->p, joint->r1));
  293. // joint->bias = cpvclamp(cpvmult(delta, -joint->constraint.biasCoef*dt_inv), joint->constraint.maxBias);
  294. Vector2 delta = (B->get_transform().get_origin() +rB) - (A->get_transform().get_origin() + rA);
  295. float _b = get_bias();
  296. _b=0.001;
  297. gbias=(delta*-(_b==0?space->get_constraint_bias():_b)*(1.0/p_step)).clamped(get_max_bias());
  298. // apply accumulated impulse
  299. A->apply_impulse(rA,-jn_acc);
  300. B->apply_impulse(rB,jn_acc);
  301. correct=true;
  302. return true;
  303. }
  304. void GrooveJoint2DSW::solve(float p_step){
  305. // compute impulse
  306. Vector2 vr = relative_velocity(A, B, rA,rB);
  307. Vector2 j = mult_k(gbias-vr, k1, k2);
  308. Vector2 jOld = jn_acc;
  309. j+=jOld;
  310. jn_acc = (((clamp * j.cross(xf_normal)) > 0) ? j : xf_normal.project(j)).clamped(jn_max);
  311. j = jn_acc - jOld;
  312. A->apply_impulse(rA,-j);
  313. B->apply_impulse(rB,j);
  314. }
  315. GrooveJoint2DSW::GrooveJoint2DSW(const Vector2& p_a_groove1,const Vector2& p_a_groove2, const Vector2& p_b_anchor, Body2DSW* p_body_a,Body2DSW* p_body_b) : Joint2DSW(_arr,2) {
  316. A=p_body_a;
  317. B=p_body_b;
  318. A_groove_1 = A->get_inv_transform().xform(p_a_groove1);
  319. A_groove_2 = A->get_inv_transform().xform(p_a_groove2);
  320. B_anchor=B->get_inv_transform().xform(p_b_anchor);
  321. A_groove_normal = -(A_groove_2 - A_groove_1).normalized().tangent();
  322. A->add_constraint(this,0);
  323. B->add_constraint(this,1);
  324. }
  325. GrooveJoint2DSW::~GrooveJoint2DSW() {
  326. A->remove_constraint(this);
  327. B->remove_constraint(this);
  328. }
  329. //////////////////////////////////////////////
  330. //////////////////////////////////////////////
  331. //////////////////////////////////////////////
  332. bool DampedSpringJoint2DSW::setup(float p_step) {
  333. rA = A->get_transform().basis_xform(anchor_A);
  334. rB = B->get_transform().basis_xform(anchor_B);
  335. Vector2 delta = (B->get_transform().get_origin() + rB) - (A->get_transform().get_origin() + rA) ;
  336. real_t dist = delta.length();
  337. if (dist)
  338. n=delta/dist;
  339. else
  340. n=Vector2();
  341. real_t k = k_scalar(A, B, rA, rB, n);
  342. n_mass = 1.0f/k;
  343. target_vrn = 0.0f;
  344. v_coef = 1.0f - Math::exp(-damping*(p_step)*k);
  345. // apply spring force
  346. real_t f_spring = (rest_length - dist) * stiffness;
  347. Vector2 j = n * f_spring*(p_step);
  348. A->apply_impulse(rA,-j);
  349. B->apply_impulse(rB,j);
  350. return true;
  351. }
  352. void DampedSpringJoint2DSW::solve(float p_step) {
  353. // compute relative velocity
  354. real_t vrn = normal_relative_velocity(A, B, rA, rB, n) - target_vrn;
  355. // compute velocity loss from drag
  356. // not 100% certain this is derived correctly, though it makes sense
  357. real_t v_damp = -vrn*v_coef;
  358. target_vrn = vrn + v_damp;
  359. Vector2 j=n*v_damp*n_mass;
  360. A->apply_impulse(rA,-j);
  361. B->apply_impulse(rB,j);
  362. }
  363. void DampedSpringJoint2DSW::set_param(Physics2DServer::DampedStringParam p_param, real_t p_value) {
  364. switch(p_param) {
  365. case Physics2DServer::DAMPED_STRING_REST_LENGTH: {
  366. rest_length=p_value;
  367. } break;
  368. case Physics2DServer::DAMPED_STRING_DAMPING: {
  369. damping=p_value;
  370. } break;
  371. case Physics2DServer::DAMPED_STRING_STIFFNESS: {
  372. stiffness=p_value;
  373. } break;
  374. }
  375. }
  376. real_t DampedSpringJoint2DSW::get_param(Physics2DServer::DampedStringParam p_param) const{
  377. switch(p_param) {
  378. case Physics2DServer::DAMPED_STRING_REST_LENGTH: {
  379. return rest_length;
  380. } break;
  381. case Physics2DServer::DAMPED_STRING_DAMPING: {
  382. return damping;
  383. } break;
  384. case Physics2DServer::DAMPED_STRING_STIFFNESS: {
  385. return stiffness;
  386. } break;
  387. }
  388. ERR_FAIL_V(0);
  389. }
  390. DampedSpringJoint2DSW::DampedSpringJoint2DSW(const Vector2& p_anchor_a,const Vector2& p_anchor_b, Body2DSW* p_body_a,Body2DSW* p_body_b) : Joint2DSW(_arr,2) {
  391. A=p_body_a;
  392. B=p_body_b;
  393. anchor_A = A->get_inv_transform().xform(p_anchor_a);
  394. anchor_B = B->get_inv_transform().xform(p_anchor_b);
  395. rest_length=p_anchor_a.distance_to(p_anchor_b);
  396. stiffness=20;
  397. damping=1.5;
  398. A->add_constraint(this,0);
  399. B->add_constraint(this,1);
  400. }
  401. DampedSpringJoint2DSW::~DampedSpringJoint2DSW() {
  402. A->remove_constraint(this);
  403. B->remove_constraint(this);
  404. }