constraint.go 25 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073
  1. package tamias
  2. var CONSTRAINT_BIAS_COEF = Float(0.1);
  3. type Constraint interface {
  4. A() (*Body)
  5. B() (*Body)
  6. Data() (interface{})
  7. MaxForce() (Float)
  8. BiasCoef() (Float)
  9. MaxBias() (Float)
  10. PreStep(dt, dt_inv int)
  11. ApplyImpulse()
  12. GetImpulse() (Float)
  13. }
  14. type constraint struct {
  15. a, b *Body;
  16. maxForce, biasCoef, maxBias Float;
  17. data interface{}
  18. }
  19. type BasicConstraint constraint
  20. func (c * constraint) Bodies() (*Body, *Body) {
  21. return c.a, c.b
  22. }
  23. func (c * constraint) MaxForce() (Float) {
  24. return c.maxForce
  25. }
  26. func (c * constraint) BiasCoef() (Float) {
  27. return c.biasCoef
  28. }
  29. func (c * constraint) MaxBias() (Float) {
  30. return c.maxBias
  31. }
  32. func (c * constraint) Init(a, b *Body) (* constraint) {
  33. c.a = a
  34. c.b = b
  35. c.maxForce = INFINITY
  36. c.biasCoef = CONSTRAINT_BIAS_COEF
  37. c.maxBias = INFINITY
  38. return c
  39. }
  40. type SpringConstraint interface {
  41. Constraint
  42. SpringTorque(Vect) (Float)
  43. }
  44. type DampedRotarySpring struct {
  45. constraint
  46. restAngle , stiffness , damping Float
  47. dt , target_wrn, iSum Float
  48. }
  49. type DampedSpring struct {
  50. constraint
  51. anchr1, anchr2 Vect
  52. restLength, stiffness, damping Float;
  53. dt, target_vrn Float
  54. r1, r2 Vect
  55. nMass Float;
  56. n Vect;
  57. }
  58. type GearJoint struct {
  59. constraint
  60. phase, ratio, ratio_inv, iSum Float
  61. bias, jAcc, jMax Float
  62. }
  63. type GrooveJoint struct {
  64. constraint
  65. grv_n, grv_a, grv_b Vect
  66. anchr2 Vect
  67. grv_tn Vect
  68. clamp Float
  69. r1, r2 Vect
  70. k1, k2 Vect
  71. jAcc Vect
  72. jMaxLen Vect
  73. bias Vect
  74. }
  75. type PinJoint struct {
  76. constraint
  77. anchr1, anchr2 Vect
  78. dist Float
  79. r1, r2 Vect
  80. n Vect
  81. nMass Float
  82. jnAcc, jnMax Float
  83. bias Float
  84. }
  85. type PivotJoint struct {
  86. constraint
  87. anchr1, anchr2 Vect
  88. r1, r2 Vect
  89. k1, k2 Vect
  90. jAcc Vect
  91. jMaxLen Float
  92. bias Vect
  93. }
  94. type RatchetJoint struct {
  95. constraint
  96. angle, phase, ratchet Float
  97. iSum Float
  98. bias Float
  99. jAcc, jMax Float
  100. }
  101. type RotaryLimitJoint struct {
  102. constraint
  103. min, max Float;
  104. iSum Float;
  105. bias Float;
  106. jAcc, jMax Float;
  107. }
  108. type SimpleMotor struct {
  109. constraint
  110. rate, iSum, jAcc, jMax Float;
  111. }
  112. type SlideJoint struct {
  113. constraint
  114. anchr1, anchr2 Vect;
  115. min, max Float;
  116. r1, r2 Vect;
  117. n Vect;
  118. nMass Float;
  119. jnAcc, jnMax Float;
  120. bias Float;
  121. }
  122. func (spring * DampedRotarySpring) SpringTorque(relativeAngle Float) (Float) {
  123. return (relativeAngle - spring.restAngle)*spring.stiffness;
  124. }
  125. func (spring * DampedRotarySpring) PreStep(dt, dt_inv Float) {
  126. a, b := spring.Bodies()
  127. spring.iSum = Float(1.0)/(a.i_inv + b.i_inv);
  128. spring.dt = dt;
  129. spring.target_wrn = Float(0.0);
  130. // apply spring torque
  131. da := a.a - b.a
  132. j_spring := spring.SpringTorque(da) * dt
  133. a.w -= j_spring * a.i_inv;
  134. b.w += j_spring * b.i_inv;
  135. }
  136. func (spring * DampedRotarySpring) ApplyImpulse() {
  137. a, b := spring.Bodies()
  138. // compute relative velocity
  139. wrn := a.w - b.w;
  140. //normal_relative_velocity(a, b, r1, r2, n) - spring.target_vrn;
  141. // compute velocity loss from drag
  142. // not 100% certain this is derived correctly, though it makes sense
  143. w_aid := (-spring.damping*spring.dt/spring.iSum).Exp()
  144. w_damp := wrn*(Float(1.0) - w_aid);
  145. spring.target_wrn = wrn - w_damp;
  146. //apply_impulses(a, b, spring.r1, spring.r2, cpvmult(spring.n, v_damp*spring.nMass));
  147. j_damp := w_damp*spring.iSum;
  148. a.w -= j_damp*a.i_inv;
  149. b.w += j_damp*b.i_inv;
  150. }
  151. func (spring * DampedRotarySpring) GetImpulse() (Float) {
  152. return Float(0.0)
  153. }
  154. func DampedRotarySpringAlloc() (* DampedRotarySpring) {
  155. return &DampedRotarySpring{}
  156. }
  157. func (spring * DampedRotarySpring) Init(a, b *Body, restAngle, stiffness,
  158. damping Float) (* DampedRotarySpring) {
  159. spring.constraint.Init(a, b)
  160. spring.restAngle = restAngle
  161. spring.stiffness = stiffness
  162. spring.damping = damping
  163. return spring
  164. }
  165. func DampedRotarySpringNew(a, b *Body, restAngle, stiffness,
  166. damping Float) (* DampedRotarySpring) {
  167. return DampedRotarySpringAlloc().Init(a, b, restAngle, stiffness, damping)
  168. }
  169. /*
  170. static cpFloat
  171. defaultSpringForce(cpDampedSpring *spring, cpFloat dist){
  172. return (spring->restLength - dist)*spring->stiffness;
  173. }
  174. static void
  175. preStep(cpDampedSpring *spring, cpFloat dt, cpFloat dt_inv)
  176. {
  177. cpBody *a = spring->constraint.a;
  178. cpBody *b = spring->constraint.b;
  179. spring->r1 = cpvrotate(spring->anchr1, a->rot);
  180. spring->r2 = cpvrotate(spring->anchr2, b->rot);
  181. cpVect delta = cpvsub(cpvadd(b->p, spring->r2), cpvadd(a->p, spring->r1));
  182. cpFloat dist = cpvlength(delta);
  183. spring->n = cpvmult(delta, 1.0f/(dist ? dist : INFINITY));
  184. // calculate mass normal
  185. spring->nMass = 1.0f/k_scalar(a, b, spring->r1, spring->r2, spring->n);
  186. spring->dt = dt;
  187. spring->target_vrn = 0.0f;
  188. // apply spring force
  189. cpFloat f_spring = spring->springForceFunc((cpConstraint *)spring, dist);
  190. apply_impulses(a, b, spring->r1, spring->r2, cpvmult(spring->n, f_spring*dt));
  191. }
  192. static void
  193. applyImpulse(cpDampedSpring *spring)
  194. {
  195. cpBody *a = spring->constraint.a;
  196. cpBody *b = spring->constraint.b;
  197. cpVect n = spring->n;
  198. cpVect r1 = spring->r1;
  199. cpVect r2 = spring->r2;
  200. // compute relative velocity
  201. cpFloat vrn = normal_relative_velocity(a, b, r1, r2, n) - spring->target_vrn;
  202. // compute velocity loss from drag
  203. // not 100% certain this is derived correctly, though it makes sense
  204. cpFloat v_damp = -vrn*(1.0f - cpfexp(-spring->damping*spring->dt/spring->nMass));
  205. spring->target_vrn = vrn + v_damp;
  206. apply_impulses(a, b, spring->r1, spring->r2, cpvmult(spring->n, v_damp*spring->nMass));
  207. }
  208. static cpFloat
  209. getImpulse(cpConstraint *constraint)
  210. {
  211. return 0.0f;
  212. }
  213. static const cpConstraintClass klass = {
  214. (cpConstraintPreStepFunction)preStep,
  215. (cpConstraintApplyImpulseFunction)applyImpulse,
  216. (cpConstraintGetImpulseFunction)getImpulse,
  217. };
  218. CP_DefineClassGetter(cpDampedSpring)
  219. cpDampedSpring *
  220. cpDampedSpringAlloc(void)
  221. {
  222. return (cpDampedSpring *)cpmalloc(sizeof(cpDampedSpring));
  223. }
  224. cpDampedSpring *
  225. cpDampedSpringInit(cpDampedSpring *spring, cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat restLength, cpFloat stiffness, cpFloat damping)
  226. {
  227. cpConstraintInit((cpConstraint *)spring, cpDampedSpringGetClass(), a, b);
  228. spring->anchr1 = anchr1;
  229. spring->anchr2 = anchr2;
  230. spring->restLength = restLength;
  231. spring->stiffness = stiffness;
  232. spring->damping = damping;
  233. spring->springForceFunc = (cpDampedSpringForceFunc)defaultSpringForce;
  234. return spring;
  235. }
  236. cpConstraint *
  237. cpDampedSpringNew(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat restLength, cpFloat stiffness, cpFloat damping)
  238. {
  239. return (cpConstraint *)cpDampedSpringInit(cpDampedSpringAlloc(), a, b, anchr1, anchr2, restLength, stiffness, damping);
  240. }
  241. static void
  242. preStep(cpGearJoint *joint, cpFloat dt, cpFloat dt_inv)
  243. {
  244. cpBody *a = joint->constraint.a;
  245. cpBody *b = joint->constraint.b;
  246. // calculate moment of inertia coefficient.
  247. joint->iSum = 1.0f/(a->i_inv*joint->ratio_inv + joint->ratio*b->i_inv);
  248. // calculate bias velocity
  249. cpFloat maxBias = joint->constraint.maxBias;
  250. joint->bias = cpfclamp(-joint->constraint.biasCoef*dt_inv*(b->a*joint->ratio - a->a - joint->phase), -maxBias, maxBias);
  251. // compute max impulse
  252. joint->jMax = J_MAX(joint, dt);
  253. // apply joint torque
  254. cpFloat j = joint->jAcc;
  255. a->w -= j*a->i_inv*joint->ratio_inv;
  256. b->w += j*b->i_inv;
  257. }
  258. static void
  259. applyImpulse(cpGearJoint *joint)
  260. {
  261. cpBody *a = joint->constraint.a;
  262. cpBody *b = joint->constraint.b;
  263. // compute relative rotational velocity
  264. cpFloat wr = b->w*joint->ratio - a->w;
  265. // compute normal impulse
  266. cpFloat j = (joint->bias - wr)*joint->iSum;
  267. cpFloat jOld = joint->jAcc;
  268. joint->jAcc = cpfclamp(jOld + j, -joint->jMax, joint->jMax);
  269. j = joint->jAcc - jOld;
  270. // apply impulse
  271. a->w -= j*a->i_inv*joint->ratio_inv;
  272. b->w += j*b->i_inv;
  273. }
  274. static cpFloat
  275. getImpulse(cpGearJoint *joint)
  276. {
  277. return cpfabs(joint->jAcc);
  278. }
  279. static const cpConstraintClass klass = {
  280. (cpConstraintPreStepFunction)preStep,
  281. (cpConstraintApplyImpulseFunction)applyImpulse,
  282. (cpConstraintGetImpulseFunction)getImpulse,
  283. };
  284. CP_DefineClassGetter(cpGearJoint)
  285. cpGearJoint *
  286. cpGearJointAlloc(void)
  287. {
  288. return (cpGearJoint *)cpmalloc(sizeof(cpGearJoint));
  289. }
  290. cpGearJoint *
  291. cpGearJointInit(cpGearJoint *joint, cpBody *a, cpBody *b, cpFloat phase, cpFloat ratio)
  292. {
  293. cpConstraintInit((cpConstraint *)joint, &klass, a, b);
  294. joint->phase = phase;
  295. joint->ratio = ratio;
  296. joint->ratio_inv = 1.0f/ratio;
  297. joint->jAcc = 0.0f;
  298. return joint;
  299. }
  300. cpConstraint *
  301. cpGearJointNew(cpBody *a, cpBody *b, cpFloat phase, cpFloat ratio)
  302. {
  303. return (cpConstraint *)cpGearJointInit(cpGearJointAlloc(), a, b, phase, ratio);
  304. }
  305. void
  306. cpGearJointSetRatio(cpConstraint *constraint, cpFloat value)
  307. {
  308. cpConstraintCheckCast(constraint, cpGearJoint);
  309. ((cpGearJoint *)constraint)->ratio = value;
  310. ((cpGearJoint *)constraint)->ratio_inv = 1.0f/value;
  311. }
  312. static void
  313. preStep(cpGrooveJoint *joint, cpFloat dt, cpFloat dt_inv)
  314. {
  315. cpBody *a = joint->constraint.a;
  316. cpBody *b = joint->constraint.b;
  317. // calculate endpoints in worldspace
  318. cpVect ta = cpBodyLocal2World(a, joint->grv_a);
  319. cpVect tb = cpBodyLocal2World(a, joint->grv_b);
  320. // calculate axis
  321. cpVect n = cpvrotate(joint->grv_n, a->rot);
  322. cpFloat d = cpvdot(ta, n);
  323. joint->grv_tn = n;
  324. joint->r2 = cpvrotate(joint->anchr2, b->rot);
  325. // calculate tangential distance along the axis of r2
  326. cpFloat td = cpvcross(cpvadd(b->p, joint->r2), n);
  327. // calculate clamping factor and r2
  328. if(td <= cpvcross(ta, n)){
  329. joint->clamp = 1.0f;
  330. joint->r1 = cpvsub(ta, a->p);
  331. } else if(td >= cpvcross(tb, n)){
  332. joint->clamp = -1.0f;
  333. joint->r1 = cpvsub(tb, a->p);
  334. } else {
  335. joint->clamp = 0.0f;
  336. joint->r1 = cpvsub(cpvadd(cpvmult(cpvperp(n), -td), cpvmult(n, d)), a->p);
  337. }
  338. // Calculate mass tensor
  339. k_tensor(a, b, joint->r1, joint->r2, &joint->k1, &joint->k2);
  340. // compute max impulse
  341. joint->jMaxLen = J_MAX(joint, dt);
  342. // calculate bias velocity
  343. cpVect delta = cpvsub(cpvadd(b->p, joint->r2), cpvadd(a->p, joint->r1));
  344. joint->bias = cpvclamp(cpvmult(delta, -joint->constraint.biasCoef*dt_inv), joint->constraint.maxBias);
  345. // apply accumulated impulse
  346. apply_impulses(a, b, joint->r1, joint->r2, joint->jAcc);
  347. }
  348. static inline cpVect
  349. grooveConstrain(cpGrooveJoint *joint, cpVect j){
  350. cpVect n = joint->grv_tn;
  351. cpVect jClamp = (joint->clamp*cpvcross(j, n) > 0.0f) ? j : cpvproject(j, n);
  352. return cpvclamp(jClamp, joint->jMaxLen);
  353. }
  354. static void
  355. applyImpulse(cpGrooveJoint *joint)
  356. {
  357. cpBody *a = joint->constraint.a;
  358. cpBody *b = joint->constraint.b;
  359. cpVect r1 = joint->r1;
  360. cpVect r2 = joint->r2;
  361. // compute impulse
  362. cpVect vr = relative_velocity(a, b, r1, r2);
  363. cpVect j = mult_k(cpvsub(joint->bias, vr), joint->k1, joint->k2);
  364. cpVect jOld = joint->jAcc;
  365. joint->jAcc = grooveConstrain(joint, cpvadd(jOld, j));
  366. j = cpvsub(joint->jAcc, jOld);
  367. // apply impulse
  368. apply_impulses(a, b, joint->r1, joint->r2, j);
  369. }
  370. static cpFloat
  371. getImpulse(cpGrooveJoint *joint)
  372. {
  373. return cpvlength(joint->jAcc);
  374. }
  375. static const cpConstraintClass klass = {
  376. (cpConstraintPreStepFunction)preStep,
  377. (cpConstraintApplyImpulseFunction)applyImpulse,
  378. (cpConstraintGetImpulseFunction)getImpulse,
  379. };
  380. CP_DefineClassGetter(cpGrooveJoint)
  381. cpGrooveJoint *
  382. cpGrooveJointAlloc(void)
  383. {
  384. return (cpGrooveJoint *)cpmalloc(sizeof(cpGrooveJoint));
  385. }
  386. cpGrooveJoint *
  387. cpGrooveJointInit(cpGrooveJoint *joint, cpBody *a, cpBody *b, cpVect groove_a, cpVect groove_b, cpVect anchr2)
  388. {
  389. cpConstraintInit((cpConstraint *)joint, &klass, a, b);
  390. joint->grv_a = groove_a;
  391. joint->grv_b = groove_b;
  392. joint->grv_n = cpvperp(cpvnormalize(cpvsub(groove_b, groove_a)));
  393. joint->anchr2 = anchr2;
  394. joint->jAcc = cpvzero;
  395. return joint;
  396. }
  397. cpConstraint *
  398. cpGrooveJointNew(cpBody *a, cpBody *b, cpVect groove_a, cpVect groove_b, cpVect anchr2)
  399. {
  400. return (cpConstraint *)cpGrooveJointInit(cpGrooveJointAlloc(), a, b, groove_a, groove_b, anchr2);
  401. }
  402. static void
  403. preStep(cpPinJoint *joint, cpFloat dt, cpFloat dt_inv)
  404. {
  405. cpBody *a = joint->constraint.a;
  406. cpBody *b = joint->constraint.b;
  407. joint->r1 = cpvrotate(joint->anchr1, a->rot);
  408. joint->r2 = cpvrotate(joint->anchr2, b->rot);
  409. cpVect delta = cpvsub(cpvadd(b->p, joint->r2), cpvadd(a->p, joint->r1));
  410. cpFloat dist = cpvlength(delta);
  411. joint->n = cpvmult(delta, 1.0f/(dist ? dist : (cpFloat)INFINITY));
  412. // calculate mass normal
  413. joint->nMass = 1.0f/k_scalar(a, b, joint->r1, joint->r2, joint->n);
  414. // calculate bias velocity
  415. cpFloat maxBias = joint->constraint.maxBias;
  416. joint->bias = cpfclamp(-joint->constraint.biasCoef*dt_inv*(dist - joint->dist), -maxBias, maxBias);
  417. // compute max impulse
  418. joint->jnMax = J_MAX(joint, dt);
  419. // apply accumulated impulse
  420. cpVect j = cpvmult(joint->n, joint->jnAcc);
  421. apply_impulses(a, b, joint->r1, joint->r2, j);
  422. }
  423. static void
  424. applyImpulse(cpPinJoint *joint)
  425. {
  426. cpBody *a = joint->constraint.a;
  427. cpBody *b = joint->constraint.b;
  428. cpVect n = joint->n;
  429. // compute relative velocity
  430. cpFloat vrn = normal_relative_velocity(a, b, joint->r1, joint->r2, n);
  431. // compute normal impulse
  432. cpFloat jn = (joint->bias - vrn)*joint->nMass;
  433. cpFloat jnOld = joint->jnAcc;
  434. joint->jnAcc = cpfclamp(jnOld + jn, -joint->jnMax, joint->jnMax);
  435. jn = joint->jnAcc - jnOld;
  436. // apply impulse
  437. apply_impulses(a, b, joint->r1, joint->r2, cpvmult(n, jn));
  438. }
  439. static cpFloat
  440. getImpulse(cpPinJoint *joint)
  441. {
  442. return cpfabs(joint->jnAcc);
  443. }
  444. static const cpConstraintClass klass = {
  445. (cpConstraintPreStepFunction)preStep,
  446. (cpConstraintApplyImpulseFunction)applyImpulse,
  447. (cpConstraintGetImpulseFunction)getImpulse,
  448. };
  449. CP_DefineClassGetter(cpPinJoint);
  450. cpPinJoint *
  451. cpPinJointAlloc(void)
  452. {
  453. return (cpPinJoint *)cpmalloc(sizeof(cpPinJoint));
  454. }
  455. cpPinJoint *
  456. cpPinJointInit(cpPinJoint *joint, cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2)
  457. {
  458. cpConstraintInit((cpConstraint *)joint, &klass, a, b);
  459. joint->anchr1 = anchr1;
  460. joint->anchr2 = anchr2;
  461. cpVect p1 = cpvadd(a->p, cpvrotate(anchr1, a->rot));
  462. cpVect p2 = cpvadd(b->p, cpvrotate(anchr2, b->rot));
  463. joint->dist = cpvlength(cpvsub(p2, p1));
  464. joint->jnAcc = 0.0f;
  465. return joint;
  466. }
  467. cpConstraint *
  468. cpPinJointNew(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2)
  469. {
  470. return (cpConstraint *)cpPinJointInit(cpPinJointAlloc(), a, b, anchr1, anchr2);
  471. }
  472. static void
  473. preStep(cpPivotJoint *joint, cpFloat dt, cpFloat dt_inv)
  474. {
  475. cpBody *a = joint->constraint.a;
  476. cpBody *b = joint->constraint.b;
  477. joint->r1 = cpvrotate(joint->anchr1, a->rot);
  478. joint->r2 = cpvrotate(joint->anchr2, b->rot);
  479. // Calculate mass tensor
  480. k_tensor(a, b, joint->r1, joint->r2, &joint->k1, &joint->k2);
  481. // compute max impulse
  482. joint->jMaxLen = J_MAX(joint, dt);
  483. // calculate bias velocity
  484. cpVect delta = cpvsub(cpvadd(b->p, joint->r2), cpvadd(a->p, joint->r1));
  485. joint->bias = cpvclamp(cpvmult(delta, -joint->constraint.biasCoef*dt_inv), joint->constraint.maxBias);
  486. // apply accumulated impulse
  487. apply_impulses(a, b, joint->r1, joint->r2, joint->jAcc);
  488. }
  489. static void
  490. applyImpulse(cpPivotJoint *joint)
  491. {
  492. cpBody *a = joint->constraint.a;
  493. cpBody *b = joint->constraint.b;
  494. cpVect r1 = joint->r1;
  495. cpVect r2 = joint->r2;
  496. // compute relative velocity
  497. cpVect vr = relative_velocity(a, b, r1, r2);
  498. // compute normal impulse
  499. cpVect j = mult_k(cpvsub(joint->bias, vr), joint->k1, joint->k2);
  500. cpVect jOld = joint->jAcc;
  501. joint->jAcc = cpvclamp(cpvadd(joint->jAcc, j), joint->jMaxLen);
  502. j = cpvsub(joint->jAcc, jOld);
  503. // apply impulse
  504. apply_impulses(a, b, joint->r1, joint->r2, j);
  505. }
  506. static cpFloat
  507. getImpulse(cpConstraint *joint)
  508. {
  509. return cpvlength(((cpPivotJoint *)joint)->jAcc);
  510. }
  511. static const cpConstraintClass klass = {
  512. (cpConstraintPreStepFunction)preStep,
  513. (cpConstraintApplyImpulseFunction)applyImpulse,
  514. (cpConstraintGetImpulseFunction)getImpulse,
  515. };
  516. CP_DefineClassGetter(cpPivotJoint)
  517. cpPivotJoint *
  518. cpPivotJointAlloc(void)
  519. {
  520. return (cpPivotJoint *)cpmalloc(sizeof(cpPivotJoint));
  521. }
  522. cpPivotJoint *
  523. cpPivotJointInit(cpPivotJoint *joint, cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2)
  524. {
  525. cpConstraintInit((cpConstraint *)joint, &klass, a, b);
  526. joint->anchr1 = anchr1;
  527. joint->anchr2 = anchr2;
  528. joint->jAcc = cpvzero;
  529. return joint;
  530. }
  531. cpConstraint *
  532. cpPivotJointNew2(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2)
  533. {
  534. return (cpConstraint *)cpPivotJointInit(cpPivotJointAlloc(), a, b, anchr1, anchr2);
  535. }
  536. cpConstraint *
  537. cpPivotJointNew(cpBody *a, cpBody *b, cpVect pivot)
  538. {
  539. return cpPivotJointNew2(a, b, cpBodyWorld2Local(a, pivot), cpBodyWorld2Local(b, pivot));
  540. }
  541. static void
  542. preStep(cpRatchetJoint *joint, cpFloat dt, cpFloat dt_inv)
  543. {
  544. cpBody *a = joint->constraint.a;
  545. cpBody *b = joint->constraint.b;
  546. cpFloat angle = joint->angle;
  547. cpFloat phase = joint->phase;
  548. cpFloat ratchet = joint->ratchet;
  549. cpFloat delta = b->a - a->a;
  550. cpFloat diff = angle - delta;
  551. cpFloat pdist = 0.0f;
  552. if(diff*ratchet > 0.0f){
  553. pdist = diff;
  554. } else {
  555. joint->angle = cpffloor((delta - phase)/ratchet)*ratchet + phase;
  556. }
  557. // calculate moment of inertia coefficient.
  558. joint->iSum = 1.0f/(a->i_inv + b->i_inv);
  559. // calculate bias velocity
  560. cpFloat maxBias = joint->constraint.maxBias;
  561. joint->bias = cpfclamp(-joint->constraint.biasCoef*dt_inv*pdist, -maxBias, maxBias);
  562. // compute max impulse
  563. joint->jMax = J_MAX(joint, dt);
  564. // If the bias is 0, the joint is not at a limit. Reset the impulse.
  565. if(!joint->bias)
  566. joint->jAcc = 0.0f;
  567. // apply joint torque
  568. a->w -= joint->jAcc*a->i_inv;
  569. b->w += joint->jAcc*b->i_inv;
  570. }
  571. static void
  572. applyImpulse(cpRatchetJoint *joint)
  573. {
  574. if(!joint->bias) return; // early exit
  575. cpBody *a = joint->constraint.a;
  576. cpBody *b = joint->constraint.b;
  577. // compute relative rotational velocity
  578. cpFloat wr = b->w - a->w;
  579. cpFloat ratchet = joint->ratchet;
  580. // compute normal impulse
  581. cpFloat j = -(joint->bias + wr)*joint->iSum;
  582. cpFloat jOld = joint->jAcc;
  583. joint->jAcc = cpfclamp((jOld + j)*ratchet, 0.0f, joint->jMax*cpfabs(ratchet))/ratchet;
  584. j = joint->jAcc - jOld;
  585. // apply impulse
  586. a->w -= j*a->i_inv;
  587. b->w += j*b->i_inv;
  588. }
  589. static cpFloat
  590. getImpulse(cpRatchetJoint *joint)
  591. {
  592. return cpfabs(joint->jAcc);
  593. }
  594. static const cpConstraintClass klass = {
  595. (cpConstraintPreStepFunction)preStep,
  596. (cpConstraintApplyImpulseFunction)applyImpulse,
  597. (cpConstraintGetImpulseFunction)getImpulse,
  598. };
  599. CP_DefineClassGetter(cpRatchetJoint)
  600. cpRatchetJoint *
  601. cpRatchetJointAlloc(void)
  602. {
  603. return (cpRatchetJoint *)cpmalloc(sizeof(cpRatchetJoint));
  604. }
  605. cpRatchetJoint *
  606. cpRatchetJointInit(cpRatchetJoint *joint, cpBody *a, cpBody *b, cpFloat phase, cpFloat ratchet)
  607. {
  608. cpConstraintInit((cpConstraint *)joint, &klass, a, b);
  609. joint->angle = 0.0f;
  610. joint->phase = phase;
  611. joint->ratchet = ratchet;
  612. joint->angle = b->a - a->a;
  613. return joint;
  614. }
  615. cpConstraint *
  616. cpRatchetJointNew(cpBody *a, cpBody *b, cpFloat phase, cpFloat ratchet)
  617. {
  618. return (cpConstraint *)cpRatchetJointInit(cpRatchetJointAlloc(), a, b, phase, ratchet);
  619. }
  620. static void
  621. preStep(cpRotaryLimitJoint *joint, cpFloat dt, cpFloat dt_inv)
  622. {
  623. cpBody *a = joint->constraint.a;
  624. cpBody *b = joint->constraint.b;
  625. cpFloat dist = b->a - a->a;
  626. cpFloat pdist = 0.0f;
  627. if(dist > joint->max) {
  628. pdist = joint->max - dist;
  629. } else if(dist < joint->min) {
  630. pdist = joint->min - dist;
  631. }
  632. // calculate moment of inertia coefficient.
  633. joint->iSum = 1.0f/(a->i_inv + b->i_inv);
  634. // calculate bias velocity
  635. cpFloat maxBias = joint->constraint.maxBias;
  636. joint->bias = cpfclamp(-joint->constraint.biasCoef*dt_inv*(pdist), -maxBias, maxBias);
  637. // compute max impulse
  638. joint->jMax = J_MAX(joint, dt);
  639. // If the bias is 0, the joint is not at a limit. Reset the impulse.
  640. if(!joint->bias)
  641. joint->jAcc = 0.0f;
  642. // apply joint torque
  643. a->w -= joint->jAcc*a->i_inv;
  644. b->w += joint->jAcc*b->i_inv;
  645. }
  646. static void
  647. applyImpulse(cpRotaryLimitJoint *joint)
  648. {
  649. if(!joint->bias) return; // early exit
  650. cpBody *a = joint->constraint.a;
  651. cpBody *b = joint->constraint.b;
  652. // compute relative rotational velocity
  653. cpFloat wr = b->w - a->w;
  654. // compute normal impulse
  655. cpFloat j = -(joint->bias + wr)*joint->iSum;
  656. cpFloat jOld = joint->jAcc;
  657. if(joint->bias < 0.0f){
  658. joint->jAcc = cpfclamp(jOld + j, 0.0f, joint->jMax);
  659. } else {
  660. joint->jAcc = cpfclamp(jOld + j, -joint->jMax, 0.0f);
  661. }
  662. j = joint->jAcc - jOld;
  663. // apply impulse
  664. a->w -= j*a->i_inv;
  665. b->w += j*b->i_inv;
  666. }
  667. static cpFloat
  668. getImpulse(cpRotaryLimitJoint *joint)
  669. {
  670. return cpfabs(joint->jAcc);
  671. }
  672. static const cpConstraintClass klass = {
  673. (cpConstraintPreStepFunction)preStep,
  674. (cpConstraintApplyImpulseFunction)applyImpulse,
  675. (cpConstraintGetImpulseFunction)getImpulse,
  676. };
  677. CP_DefineClassGetter(cpRotaryLimitJoint)
  678. cpRotaryLimitJoint *
  679. cpRotaryLimitJointAlloc(void)
  680. {
  681. return (cpRotaryLimitJoint *)cpmalloc(sizeof(cpRotaryLimitJoint));
  682. }
  683. cpRotaryLimitJoint *
  684. cpRotaryLimitJointInit(cpRotaryLimitJoint *joint, cpBody *a, cpBody *b, cpFloat min, cpFloat max)
  685. {
  686. cpConstraintInit((cpConstraint *)joint, &klass, a, b);
  687. joint->min = min;
  688. joint->max = max;
  689. joint->jAcc = 0.0f;
  690. return joint;
  691. }
  692. cpConstraint *
  693. cpRotaryLimitJointNew(cpBody *a, cpBody *b, cpFloat min, cpFloat max)
  694. {
  695. return (cpConstraint *)cpRotaryLimitJointInit(cpRotaryLimitJointAlloc(), a, b, min, max);
  696. }
  697. static void
  698. preStep(cpSimpleMotor *joint, cpFloat dt, cpFloat dt_inv)
  699. {
  700. cpBody *a = joint->constraint.a;
  701. cpBody *b = joint->constraint.b;
  702. // calculate moment of inertia coefficient.
  703. joint->iSum = 1.0f/(a->i_inv + b->i_inv);
  704. // compute max impulse
  705. joint->jMax = J_MAX(joint, dt);
  706. // apply joint torque
  707. a->w -= joint->jAcc*a->i_inv;
  708. b->w += joint->jAcc*b->i_inv;
  709. }
  710. static void
  711. applyImpulse(cpSimpleMotor *joint)
  712. {
  713. cpBody *a = joint->constraint.a;
  714. cpBody *b = joint->constraint.b;
  715. // compute relative rotational velocity
  716. cpFloat wr = b->w - a->w + joint->rate;
  717. // compute normal impulse
  718. cpFloat j = -wr*joint->iSum;
  719. cpFloat jOld = joint->jAcc;
  720. joint->jAcc = cpfclamp(jOld + j, -joint->jMax, joint->jMax);
  721. j = joint->jAcc - jOld;
  722. // apply impulse
  723. a->w -= j*a->i_inv;
  724. b->w += j*b->i_inv;
  725. }
  726. static cpFloat
  727. getImpulse(cpSimpleMotor *joint)
  728. {
  729. return cpfabs(joint->jAcc);
  730. }
  731. static const cpConstraintClass klass = {
  732. (cpConstraintPreStepFunction)preStep,
  733. (cpConstraintApplyImpulseFunction)applyImpulse,
  734. (cpConstraintGetImpulseFunction)getImpulse,
  735. };
  736. CP_DefineClassGetter(cpSimpleMotor)
  737. cpSimpleMotor *
  738. cpSimpleMotorAlloc(void)
  739. {
  740. return (cpSimpleMotor *)cpmalloc(sizeof(cpSimpleMotor));
  741. }
  742. cpSimpleMotor *
  743. cpSimpleMotorInit(cpSimpleMotor *joint, cpBody *a, cpBody *b, cpFloat rate)
  744. {
  745. cpConstraintInit((cpConstraint *)joint, &klass, a, b);
  746. joint->rate = rate;
  747. joint->jAcc = 0.0f;
  748. return joint;
  749. }
  750. cpConstraint *
  751. cpSimpleMotorNew(cpBody *a, cpBody *b, cpFloat rate)
  752. {
  753. return (cpConstraint *)cpSimpleMotorInit(cpSimpleMotorAlloc(), a, b, rate);
  754. }
  755. static void
  756. preStep(cpSlideJoint *joint, cpFloat dt, cpFloat dt_inv)
  757. {
  758. cpBody *a = joint->constraint.a;
  759. cpBody *b = joint->constraint.b;
  760. joint->r1 = cpvrotate(joint->anchr1, a->rot);
  761. joint->r2 = cpvrotate(joint->anchr2, b->rot);
  762. cpVect delta = cpvsub(cpvadd(b->p, joint->r2), cpvadd(a->p, joint->r1));
  763. cpFloat dist = cpvlength(delta);
  764. cpFloat pdist = 0.0f;
  765. if(dist > joint->max) {
  766. pdist = dist - joint->max;
  767. } else if(dist < joint->min) {
  768. pdist = joint->min - dist;
  769. dist = -dist;
  770. }
  771. joint->n = cpvmult(delta, 1.0f/(dist ? dist : (cpFloat)INFINITY));
  772. // calculate mass normal
  773. joint->nMass = 1.0f/k_scalar(a, b, joint->r1, joint->r2, joint->n);
  774. // calculate bias velocity
  775. cpFloat maxBias = joint->constraint.maxBias;
  776. joint->bias = cpfclamp(-joint->constraint.biasCoef*dt_inv*(pdist), -maxBias, maxBias);
  777. // compute max impulse
  778. joint->jnMax = J_MAX(joint, dt);
  779. // apply accumulated impulse
  780. if(!joint->bias) //{
  781. // if bias is 0, then the joint is not at a limit.
  782. joint->jnAcc = 0.0f;
  783. // } else {
  784. cpVect j = cpvmult(joint->n, joint->jnAcc);
  785. apply_impulses(a, b, joint->r1, joint->r2, j);
  786. // }
  787. }
  788. static void
  789. applyImpulse(cpSlideJoint *joint)
  790. {
  791. if(!joint->bias) return; // early exit
  792. cpBody *a = joint->constraint.a;
  793. cpBody *b = joint->constraint.b;
  794. cpVect n = joint->n;
  795. cpVect r1 = joint->r1;
  796. cpVect r2 = joint->r2;
  797. // compute relative velocity
  798. cpVect vr = relative_velocity(a, b, r1, r2);
  799. cpFloat vrn = cpvdot(vr, n);
  800. // compute normal impulse
  801. cpFloat jn = (joint->bias - vrn)*joint->nMass;
  802. cpFloat jnOld = joint->jnAcc;
  803. joint->jnAcc = cpfclamp(jnOld + jn, -joint->jnMax, 0.0f);
  804. jn = joint->jnAcc - jnOld;
  805. // apply impulse
  806. apply_impulses(a, b, joint->r1, joint->r2, cpvmult(n, jn));
  807. }
  808. static cpFloat
  809. getImpulse(cpConstraint *joint)
  810. {
  811. return cpfabs(((cpSlideJoint *)joint)->jnAcc);
  812. }
  813. static const cpConstraintClass klass = {
  814. (cpConstraintPreStepFunction)preStep,
  815. (cpConstraintApplyImpulseFunction)applyImpulse,
  816. (cpConstraintGetImpulseFunction)getImpulse,
  817. };
  818. CP_DefineClassGetter(cpSlideJoint)
  819. cpSlideJoint *
  820. cpSlideJointAlloc(void)
  821. {
  822. return (cpSlideJoint *)cpmalloc(sizeof(cpSlideJoint));
  823. }
  824. cpSlideJoint *
  825. cpSlideJointInit(cpSlideJoint *joint, cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat min, cpFloat max)
  826. {
  827. cpConstraintInit((cpConstraint *)joint, &klass, a, b);
  828. joint->anchr1 = anchr1;
  829. joint->anchr2 = anchr2;
  830. joint->min = min;
  831. joint->max = max;
  832. joint->jnAcc = 0.0f;
  833. return joint;
  834. }
  835. cpConstraint *
  836. cpSlideJointNew(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat min, cpFloat max)
  837. {
  838. return (cpConstraint *)cpSlideJointInit(cpSlideJointAlloc(), a, b, anchr1, anchr2, min, max);
  839. }
  840. */