b2_rope.cpp
Go to the documentation of this file.
1 // MIT License
2 
3 // Copyright (c) 2019 Erin Catto
4 
5 // Permission is hereby granted, free of charge, to any person obtaining a copy
6 // of this software and associated documentation files (the "Software"), to deal
7 // in the Software without restriction, including without limitation the rights
8 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 // copies of the Software, and to permit persons to whom the Software is
10 // furnished to do so, subject to the following conditions:
11 
12 // The above copyright notice and this permission notice shall be included in all
13 // copies or substantial portions of the Software.
14 
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 // SOFTWARE.
22 
23 #include "box2d/b2_draw.h"
24 #include "box2d/b2_rope.h"
25 
26 #include <stdio.h>
27 
29 {
32  float L;
33  float lambda;
34  float spring;
35  float damper;
36 };
37 
38 struct b2RopeBend
39 {
43  float lambda;
44  float L1, L2;
45  float alpha1, alpha2;
46  float spring;
47  float damper;
48 };
49 
51 {
53  m_count = 0;
54  m_stretchCount = 0;
55  m_bendCount = 0;
56  m_stretchConstraints = nullptr;
57  m_bendConstraints = nullptr;
58  m_bindPositions = nullptr;
59  m_ps = nullptr;
60  m_p0s = nullptr;
61  m_vs = nullptr;
62  m_invMasses = nullptr;
64 }
65 
67 {
71  b2Free(m_ps);
72  b2Free(m_p0s);
73  b2Free(m_vs);
75 }
76 
77 void b2Rope::Create(const b2RopeDef& def)
78 {
79  b2Assert(def.count >= 3);
80  m_position = def.position;
81  m_count = def.count;
83  m_ps = (b2Vec2*)b2Alloc(m_count * sizeof(b2Vec2));
84  m_p0s = (b2Vec2*)b2Alloc(m_count * sizeof(b2Vec2));
85  m_vs = (b2Vec2*)b2Alloc(m_count * sizeof(b2Vec2));
86  m_invMasses = (float*)b2Alloc(m_count * sizeof(float));
87 
88  for (int32 i = 0; i < m_count; ++i)
89  {
90  m_bindPositions[i] = def.vertices[i];
91  m_ps[i] = def.vertices[i] + m_position;
92  m_p0s[i] = def.vertices[i] + m_position;
93  m_vs[i].SetZero();
94 
95  float m = def.masses[i];
96  if (m > 0.0f)
97  {
98  m_invMasses[i] = 1.0f / m;
99  }
100  else
101  {
102  m_invMasses[i] = 0.0f;
103  }
104  }
105 
106  m_stretchCount = m_count - 1;
107  m_bendCount = m_count - 2;
108 
111 
112  for (int32 i = 0; i < m_stretchCount; ++i)
113  {
115 
116  b2Vec2 p1 = m_ps[i];
117  b2Vec2 p2 = m_ps[i+1];
118 
119  c.i1 = i;
120  c.i2 = i + 1;
121  c.L = b2Distance(p1, p2);
122  c.invMass1 = m_invMasses[i];
123  c.invMass2 = m_invMasses[i + 1];
124  c.lambda = 0.0f;
125  c.damper = 0.0f;
126  c.spring = 0.0f;
127  }
128 
129  for (int32 i = 0; i < m_bendCount; ++i)
130  {
132 
133  b2Vec2 p1 = m_ps[i];
134  b2Vec2 p2 = m_ps[i + 1];
135  b2Vec2 p3 = m_ps[i + 2];
136 
137  c.i1 = i;
138  c.i2 = i + 1;
139  c.i3 = i + 2;
140  c.invMass1 = m_invMasses[i];
141  c.invMass2 = m_invMasses[i + 1];
142  c.invMass3 = m_invMasses[i + 2];
143  c.invEffectiveMass = 0.0f;
144  c.L1 = b2Distance(p1, p2);
145  c.L2 = b2Distance(p2, p3);
146  c.lambda = 0.0f;
147 
148  // Pre-compute effective mass (TODO use flattened config)
149  b2Vec2 e1 = p2 - p1;
150  b2Vec2 e2 = p3 - p2;
151  float L1sqr = e1.LengthSquared();
152  float L2sqr = e2.LengthSquared();
153 
154  if (L1sqr * L2sqr == 0.0f)
155  {
156  continue;
157  }
158 
159  b2Vec2 Jd1 = (-1.0f / L1sqr) * e1.Skew();
160  b2Vec2 Jd2 = (1.0f / L2sqr) * e2.Skew();
161 
162  b2Vec2 J1 = -Jd1;
163  b2Vec2 J2 = Jd1 - Jd2;
164  b2Vec2 J3 = Jd2;
165 
166  c.invEffectiveMass = c.invMass1 * b2Dot(J1, J1) + c.invMass2 * b2Dot(J2, J2) + c.invMass3 * b2Dot(J3, J3);
167 
168  b2Vec2 r = p3 - p1;
169 
170  float rr = r.LengthSquared();
171  if (rr == 0.0f)
172  {
173  continue;
174  }
175 
176  // a1 = h2 / (h1 + h2)
177  // a2 = h1 / (h1 + h2)
178  c.alpha1 = b2Dot(e2, r) / rr;
179  c.alpha2 = b2Dot(e1, r) / rr;
180  }
181 
182  m_gravity = def.gravity;
183 
184  SetTuning(def.tuning);
185 }
186 
187 void b2Rope::SetTuning(const b2RopeTuning& tuning)
188 {
189  m_tuning = tuning;
190 
191  // Pre-compute spring and damper values based on tuning
192 
193  const float bendOmega = 2.0f * b2_pi * m_tuning.bendHertz;
194 
195  for (int32 i = 0; i < m_bendCount; ++i)
196  {
198 
199  float L1sqr = c.L1 * c.L1;
200  float L2sqr = c.L2 * c.L2;
201 
202  if (L1sqr * L2sqr == 0.0f)
203  {
204  c.spring = 0.0f;
205  c.damper = 0.0f;
206  continue;
207  }
208 
209  // Flatten the triangle formed by the two edges
210  float J2 = 1.0f / c.L1 + 1.0f / c.L2;
211  float sum = c.invMass1 / L1sqr + c.invMass2 * J2 * J2 + c.invMass3 / L2sqr;
212  if (sum == 0.0f)
213  {
214  c.spring = 0.0f;
215  c.damper = 0.0f;
216  continue;
217  }
218 
219  float mass = 1.0f / sum;
220 
221  c.spring = mass * bendOmega * bendOmega;
222  c.damper = 2.0f * mass * m_tuning.bendDamping * bendOmega;
223  }
224 
225  const float stretchOmega = 2.0f * b2_pi * m_tuning.stretchHertz;
226 
227  for (int32 i = 0; i < m_stretchCount; ++i)
228  {
230 
231  float sum = c.invMass1 + c.invMass2;
232  if (sum == 0.0f)
233  {
234  continue;
235  }
236 
237  float mass = 1.0f / sum;
238 
239  c.spring = mass * stretchOmega * stretchOmega;
240  c.damper = 2.0f * mass * m_tuning.stretchDamping * stretchOmega;
241  }
242 }
243 
244 void b2Rope::Step(float dt, int32 iterations, const b2Vec2& position)
245 {
246  if (dt == 0.0)
247  {
248  return;
249  }
250 
251  const float inv_dt = 1.0f / dt;
252  float d = expf(- dt * m_tuning.damping);
253 
254  // Apply gravity and damping
255  for (int32 i = 0; i < m_count; ++i)
256  {
257  if (m_invMasses[i] > 0.0f)
258  {
259  m_vs[i] *= d;
260  m_vs[i] += dt * m_gravity;
261  }
262  else
263  {
264  m_vs[i] = inv_dt * (m_bindPositions[i] + position - m_p0s[i]);
265  }
266  }
267 
268  // Apply bending spring
270  {
271  ApplyBendForces(dt);
272  }
273 
274  for (int32 i = 0; i < m_bendCount; ++i)
275  {
276  m_bendConstraints[i].lambda = 0.0f;
277  }
278 
279  for (int32 i = 0; i < m_stretchCount; ++i)
280  {
281  m_stretchConstraints[i].lambda = 0.0f;
282  }
283 
284  // Update position
285  for (int32 i = 0; i < m_count; ++i)
286  {
287  m_ps[i] += dt * m_vs[i];
288  }
289 
290  // Solve constraints
291  for (int32 i = 0; i < iterations; ++i)
292  {
294  {
296  }
298  {
300  }
302  {
304  }
306  {
308  }
310  {
312  }
313 
315  {
317  }
319  {
320  SolveStretch_XPBD(dt);
321  }
322  }
323 
324  // Constrain velocity
325  for (int32 i = 0; i < m_count; ++i)
326  {
327  m_vs[i] = inv_dt * (m_ps[i] - m_p0s[i]);
328  m_p0s[i] = m_ps[i];
329  }
330 }
331 
332 void b2Rope::Reset(const b2Vec2& position)
333 {
334  m_position = position;
335 
336  for (int32 i = 0; i < m_count; ++i)
337  {
338  m_ps[i] = m_bindPositions[i] + m_position;
339  m_p0s[i] = m_bindPositions[i] + m_position;
340  m_vs[i].SetZero();
341  }
342 
343  for (int32 i = 0; i < m_bendCount; ++i)
344  {
345  m_bendConstraints[i].lambda = 0.0f;
346  }
347 
348  for (int32 i = 0; i < m_stretchCount; ++i)
349  {
350  m_stretchConstraints[i].lambda = 0.0f;
351  }
352 }
353 
355 {
356  const float stiffness = m_tuning.stretchStiffness;
357 
358  for (int32 i = 0; i < m_stretchCount; ++i)
359  {
360  const b2RopeStretch& c = m_stretchConstraints[i];
361 
362  b2Vec2 p1 = m_ps[c.i1];
363  b2Vec2 p2 = m_ps[c.i2];
364 
365  b2Vec2 d = p2 - p1;
366  float L = d.Normalize();
367 
368  float sum = c.invMass1 + c.invMass2;
369  if (sum == 0.0f)
370  {
371  continue;
372  }
373 
374  float s1 = c.invMass1 / sum;
375  float s2 = c.invMass2 / sum;
376 
377  p1 -= stiffness * s1 * (c.L - L) * d;
378  p2 += stiffness * s2 * (c.L - L) * d;
379 
380  m_ps[c.i1] = p1;
381  m_ps[c.i2] = p2;
382  }
383 }
384 
386 {
387  b2Assert(dt > 0.0f);
388 
389  for (int32 i = 0; i < m_stretchCount; ++i)
390  {
392 
393  b2Vec2 p1 = m_ps[c.i1];
394  b2Vec2 p2 = m_ps[c.i2];
395 
396  b2Vec2 dp1 = p1 - m_p0s[c.i1];
397  b2Vec2 dp2 = p2 - m_p0s[c.i2];
398 
399  b2Vec2 u = p2 - p1;
400  float L = u.Normalize();
401 
402  b2Vec2 J1 = -u;
403  b2Vec2 J2 = u;
404 
405  float sum = c.invMass1 + c.invMass2;
406  if (sum == 0.0f)
407  {
408  continue;
409  }
410 
411  const float alpha = 1.0f / (c.spring * dt * dt); // 1 / kg
412  const float beta = dt * dt * c.damper; // kg * s
413  const float sigma = alpha * beta / dt; // non-dimensional
414  float C = L - c.L;
415 
416  // This is using the initial velocities
417  float Cdot = b2Dot(J1, dp1) + b2Dot(J2, dp2);
418 
419  float B = C + alpha * c.lambda + sigma * Cdot;
420  float sum2 = (1.0f + sigma) * sum + alpha;
421 
422  float impulse = -B / sum2;
423 
424  p1 += (c.invMass1 * impulse) * J1;
425  p2 += (c.invMass2 * impulse) * J2;
426 
427  m_ps[c.i1] = p1;
428  m_ps[c.i2] = p2;
429  c.lambda += impulse;
430  }
431 }
432 
434 {
435  const float stiffness = m_tuning.bendStiffness;
436 
437  for (int32 i = 0; i < m_bendCount; ++i)
438  {
439  const b2RopeBend& c = m_bendConstraints[i];
440 
441  b2Vec2 p1 = m_ps[c.i1];
442  b2Vec2 p2 = m_ps[c.i2];
443  b2Vec2 p3 = m_ps[c.i3];
444 
445  b2Vec2 d1 = p2 - p1;
446  b2Vec2 d2 = p3 - p2;
447  float a = b2Cross(d1, d2);
448  float b = b2Dot(d1, d2);
449 
450  float angle = b2Atan2(a, b);
451 
452  float L1sqr, L2sqr;
453 
454  if (m_tuning.isometric)
455  {
456  L1sqr = c.L1 * c.L1;
457  L2sqr = c.L2 * c.L2;
458  }
459  else
460  {
461  L1sqr = d1.LengthSquared();
462  L2sqr = d2.LengthSquared();
463  }
464 
465  if (L1sqr * L2sqr == 0.0f)
466  {
467  continue;
468  }
469 
470  b2Vec2 Jd1 = (-1.0f / L1sqr) * d1.Skew();
471  b2Vec2 Jd2 = (1.0f / L2sqr) * d2.Skew();
472 
473  b2Vec2 J1 = -Jd1;
474  b2Vec2 J2 = Jd1 - Jd2;
475  b2Vec2 J3 = Jd2;
476 
477  float sum;
479  {
480  sum = c.invEffectiveMass;
481  }
482  else
483  {
484  sum = c.invMass1 * b2Dot(J1, J1) + c.invMass2 * b2Dot(J2, J2) + c.invMass3 * b2Dot(J3, J3);
485  }
486 
487  if (sum == 0.0f)
488  {
489  sum = c.invEffectiveMass;
490  }
491 
492  float impulse = -stiffness * angle / sum;
493 
494  p1 += (c.invMass1 * impulse) * J1;
495  p2 += (c.invMass2 * impulse) * J2;
496  p3 += (c.invMass3 * impulse) * J3;
497 
498  m_ps[c.i1] = p1;
499  m_ps[c.i2] = p2;
500  m_ps[c.i3] = p3;
501  }
502 }
503 
505 {
506  b2Assert(dt > 0.0f);
507 
508  for (int32 i = 0; i < m_bendCount; ++i)
509  {
511 
512  b2Vec2 p1 = m_ps[c.i1];
513  b2Vec2 p2 = m_ps[c.i2];
514  b2Vec2 p3 = m_ps[c.i3];
515 
516  b2Vec2 dp1 = p1 - m_p0s[c.i1];
517  b2Vec2 dp2 = p2 - m_p0s[c.i2];
518  b2Vec2 dp3 = p3 - m_p0s[c.i3];
519 
520  b2Vec2 d1 = p2 - p1;
521  b2Vec2 d2 = p3 - p2;
522 
523  float L1sqr, L2sqr;
524 
525  if (m_tuning.isometric)
526  {
527  L1sqr = c.L1 * c.L1;
528  L2sqr = c.L2 * c.L2;
529  }
530  else
531  {
532  L1sqr = d1.LengthSquared();
533  L2sqr = d2.LengthSquared();
534  }
535 
536  if (L1sqr * L2sqr == 0.0f)
537  {
538  continue;
539  }
540 
541  float a = b2Cross(d1, d2);
542  float b = b2Dot(d1, d2);
543 
544  float angle = b2Atan2(a, b);
545 
546  b2Vec2 Jd1 = (-1.0f / L1sqr) * d1.Skew();
547  b2Vec2 Jd2 = (1.0f / L2sqr) * d2.Skew();
548 
549  b2Vec2 J1 = -Jd1;
550  b2Vec2 J2 = Jd1 - Jd2;
551  b2Vec2 J3 = Jd2;
552 
553  float sum;
555  {
556  sum = c.invEffectiveMass;
557  }
558  else
559  {
560  sum = c.invMass1 * b2Dot(J1, J1) + c.invMass2 * b2Dot(J2, J2) + c.invMass3 * b2Dot(J3, J3);
561  }
562 
563  if (sum == 0.0f)
564  {
565  continue;
566  }
567 
568  const float alpha = 1.0f / (c.spring * dt * dt);
569  const float beta = dt * dt * c.damper;
570  const float sigma = alpha * beta / dt;
571  float C = angle;
572 
573  // This is using the initial velocities
574  float Cdot = b2Dot(J1, dp1) + b2Dot(J2, dp2) + b2Dot(J3, dp3);
575 
576  float B = C + alpha * c.lambda + sigma * Cdot;
577  float sum2 = (1.0f + sigma) * sum + alpha;
578 
579  float impulse = -B / sum2;
580 
581  p1 += (c.invMass1 * impulse) * J1;
582  p2 += (c.invMass2 * impulse) * J2;
583  p3 += (c.invMass3 * impulse) * J3;
584 
585  m_ps[c.i1] = p1;
586  m_ps[c.i2] = p2;
587  m_ps[c.i3] = p3;
588  c.lambda += impulse;
589  }
590 }
591 
593 {
594  // omega = 2 * pi * hz
595  const float omega = 2.0f * b2_pi * m_tuning.bendHertz;
596 
597  for (int32 i = 0; i < m_bendCount; ++i)
598  {
599  const b2RopeBend& c = m_bendConstraints[i];
600 
601  b2Vec2 p1 = m_ps[c.i1];
602  b2Vec2 p2 = m_ps[c.i2];
603  b2Vec2 p3 = m_ps[c.i3];
604 
605  b2Vec2 v1 = m_vs[c.i1];
606  b2Vec2 v2 = m_vs[c.i2];
607  b2Vec2 v3 = m_vs[c.i3];
608 
609  b2Vec2 d1 = p2 - p1;
610  b2Vec2 d2 = p3 - p2;
611 
612  float L1sqr, L2sqr;
613 
614  if (m_tuning.isometric)
615  {
616  L1sqr = c.L1 * c.L1;
617  L2sqr = c.L2 * c.L2;
618  }
619  else
620  {
621  L1sqr = d1.LengthSquared();
622  L2sqr = d2.LengthSquared();
623  }
624 
625  if (L1sqr * L2sqr == 0.0f)
626  {
627  continue;
628  }
629 
630  float a = b2Cross(d1, d2);
631  float b = b2Dot(d1, d2);
632 
633  float angle = b2Atan2(a, b);
634 
635  b2Vec2 Jd1 = (-1.0f / L1sqr) * d1.Skew();
636  b2Vec2 Jd2 = (1.0f / L2sqr) * d2.Skew();
637 
638  b2Vec2 J1 = -Jd1;
639  b2Vec2 J2 = Jd1 - Jd2;
640  b2Vec2 J3 = Jd2;
641 
642  float sum;
644  {
645  sum = c.invEffectiveMass;
646  }
647  else
648  {
649  sum = c.invMass1 * b2Dot(J1, J1) + c.invMass2 * b2Dot(J2, J2) + c.invMass3 * b2Dot(J3, J3);
650  }
651 
652  if (sum == 0.0f)
653  {
654  continue;
655  }
656 
657  float mass = 1.0f / sum;
658 
659  const float spring = mass * omega * omega;
660  const float damper = 2.0f * mass * m_tuning.bendDamping * omega;
661 
662  float C = angle;
663  float Cdot = b2Dot(J1, v1) + b2Dot(J2, v2) + b2Dot(J3, v3);
664 
665  float impulse = -dt * (spring * C + damper * Cdot);
666 
667  m_vs[c.i1] += (c.invMass1 * impulse) * J1;
668  m_vs[c.i2] += (c.invMass2 * impulse) * J2;
669  m_vs[c.i3] += (c.invMass3 * impulse) * J3;
670  }
671 }
672 
674 {
675  const float stiffness = m_tuning.bendStiffness;
676 
677  for (int32 i = 0; i < m_bendCount; ++i)
678  {
679  const b2RopeBend& c = m_bendConstraints[i];
680 
681  int32 i1 = c.i1;
682  int32 i2 = c.i3;
683 
684  b2Vec2 p1 = m_ps[i1];
685  b2Vec2 p2 = m_ps[i2];
686 
687  b2Vec2 d = p2 - p1;
688  float L = d.Normalize();
689 
690  float sum = c.invMass1 + c.invMass3;
691  if (sum == 0.0f)
692  {
693  continue;
694  }
695 
696  float s1 = c.invMass1 / sum;
697  float s2 = c.invMass3 / sum;
698 
699  p1 -= stiffness * s1 * (c.L1 + c.L2 - L) * d;
700  p2 += stiffness * s2 * (c.L1 + c.L2 - L) * d;
701 
702  m_ps[i1] = p1;
703  m_ps[i2] = p2;
704  }
705 }
706 
707 // Constraint based implementation of:
708 // P. Volino: Simple Linear Bending Stiffness in Particle Systems
710 {
711  const float stiffness = m_tuning.bendStiffness;
712 
713  for (int32 i = 0; i < m_bendCount; ++i)
714  {
715  const b2RopeBend& c = m_bendConstraints[i];
716 
717  b2Vec2 p1 = m_ps[c.i1];
718  b2Vec2 p2 = m_ps[c.i2];
719  b2Vec2 p3 = m_ps[c.i3];
720 
721  // Barycentric coordinates are held constant
722  b2Vec2 d = c.alpha1 * p1 + c.alpha2 * p3 - p2;
723  float dLen = d.Length();
724 
725  if (dLen == 0.0f)
726  {
727  continue;
728  }
729 
730  b2Vec2 dHat = (1.0f / dLen) * d;
731 
732  b2Vec2 J1 = c.alpha1 * dHat;
733  b2Vec2 J2 = -dHat;
734  b2Vec2 J3 = c.alpha2 * dHat;
735 
736  float sum = c.invMass1 * c.alpha1 * c.alpha1 + c.invMass2 + c.invMass3 * c.alpha2 * c.alpha2;
737 
738  if (sum == 0.0f)
739  {
740  continue;
741  }
742 
743  float C = dLen;
744  float mass = 1.0f / sum;
745  float impulse = -stiffness * mass * C;
746 
747  p1 += (c.invMass1 * impulse) * J1;
748  p2 += (c.invMass2 * impulse) * J2;
749  p3 += (c.invMass3 * impulse) * J3;
750 
751  m_ps[c.i1] = p1;
752  m_ps[c.i2] = p2;
753  m_ps[c.i3] = p3;
754  }
755 }
756 
757 // M. Kelager: A Triangle Bending Constraint Model for PBD
759 {
760  const float stiffness = m_tuning.bendStiffness;
761 
762  for (int32 i = 0; i < m_bendCount; ++i)
763  {
764  const b2RopeBend& c = m_bendConstraints[i];
765 
766  b2Vec2 b0 = m_ps[c.i1];
767  b2Vec2 v = m_ps[c.i2];
768  b2Vec2 b1 = m_ps[c.i3];
769 
770  float wb0 = c.invMass1;
771  float wv = c.invMass2;
772  float wb1 = c.invMass3;
773 
774  float W = wb0 + wb1 + 2.0f * wv;
775  float invW = stiffness / W;
776 
777  b2Vec2 d = v - (1.0f / 3.0f) * (b0 + v + b1);
778 
779  b2Vec2 db0 = 2.0f * wb0 * invW * d;
780  b2Vec2 dv = -4.0f * wv * invW * d;
781  b2Vec2 db1 = 2.0f * wb1 * invW * d;
782 
783  b0 += db0;
784  v += dv;
785  b1 += db1;
786 
787  m_ps[c.i1] = b0;
788  m_ps[c.i2] = v;
789  m_ps[c.i3] = b1;
790  }
791 }
792 
793 void b2Rope::Draw(b2Draw* draw) const
794 {
795  b2Color c(0.4f, 0.5f, 0.7f);
796  b2Color pg(0.1f, 0.8f, 0.1f);
797  b2Color pd(0.7f, 0.2f, 0.4f);
798 
799  for (int32 i = 0; i < m_count - 1; ++i)
800  {
801  draw->DrawSegment(m_ps[i], m_ps[i+1], c);
802 
803  const b2Color& pc = m_invMasses[i] > 0.0f ? pd : pg;
804  draw->DrawPoint(m_ps[i], 5.0f, pc);
805  }
806 
807  const b2Color& pc = m_invMasses[m_count - 1] > 0.0f ? pd : pg;
808  draw->DrawPoint(m_ps[m_count - 1], 5.0f, pc);
809 }
b2_pbdTriangleBendingModel
@ b2_pbdTriangleBendingModel
Definition: b2_rope.h:46
b2RopeBend::invMass1
float invMass1
Definition: b2_rope.cpp:41
b2RopeDef::vertices
b2Vec2 * vertices
Definition: b2_rope.h:93
b2Cross
float b2Cross(const b2Vec2 &a, const b2Vec2 &b)
Perform the cross product on two vectors. In 2D this produces a scalar.
Definition: b2_math.h:401
b2RopeBend::alpha2
float alpha2
Definition: b2_rope.cpp:45
b2RopeStretch
Definition: b2_rope.cpp:28
b2_xpbdStretchingModel
@ b2_xpbdStretchingModel
Definition: b2_rope.h:36
b2Rope::SolveBend_PBD_Distance
void SolveBend_PBD_Distance()
Definition: b2_rope.cpp:673
b2Alloc
void * b2Alloc(int32 size)
Implement this function to use your own memory allocator.
Definition: b2_settings.h:100
angle
TFSIMD_FORCE_INLINE tfScalar angle(const Quaternion &q1, const Quaternion &q2)
b2_rope.h
b2RopeTuning::bendStiffness
float bendStiffness
Definition: b2_rope.h:72
b2RopeBend::i3
int32 i3
Definition: b2_rope.cpp:40
b2Rope::SolveBend_XPBD_Angle
void SolveBend_XPBD_Angle(float dt)
Definition: b2_rope.cpp:504
b2Rope::m_vs
b2Vec2 * m_vs
Definition: b2_rope.h:145
b2RopeDef::gravity
b2Vec2 gravity
Definition: b2_rope.h:96
b2Rope::b2Rope
b2Rope()
Definition: b2_rope.cpp:50
b2RopeTuning::isometric
bool isometric
Definition: b2_rope.h:75
b2RopeDef
Definition: b2_rope.h:81
b2RopeStretch::invMass1
float invMass1
Definition: b2_rope.cpp:31
b2Vec2::Normalize
float Normalize()
Convert this vector into a unit vector. Returns the length.
Definition: b2_math.h:102
b2Draw::DrawSegment
virtual void DrawSegment(const b2Vec2 &p1, const b2Vec2 &p2, const b2Color &color)=0
Draw a line segment.
b2Rope::SolveBend_PBD_Triangle
void SolveBend_PBD_Triangle()
Definition: b2_rope.cpp:758
b2_pbdAngleBendingModel
@ b2_pbdAngleBendingModel
Definition: b2_rope.h:42
b2RopeStretch::i1
int32 i1
Definition: b2_rope.cpp:30
b2Vec2::Skew
b2Vec2 Skew() const
Get the skew vector such that dot(skew_vec, other) == cross(vec, other)
Definition: b2_math.h:123
b2Distance
B2_API void b2Distance(b2DistanceOutput *output, b2SimplexCache *cache, const b2DistanceInput *input)
Definition: b2_distance.cpp:454
b2Rope::SolveBend_PBD_Height
void SolveBend_PBD_Height()
Definition: b2_rope.cpp:709
b2Rope::m_bindPositions
b2Vec2 * m_bindPositions
Definition: b2_rope.h:142
b2Vec2::SetZero
void SetZero()
Set this vector to all zeros.
Definition: b2_math.h:50
b2RopeBend::L2
float L2
Definition: b2_rope.cpp:44
b2RopeDef::count
int32 count
Definition: b2_rope.h:94
b2Rope::Draw
void Draw(b2Draw *draw) const
Definition: b2_rope.cpp:793
b2Vec2
A 2D column vector.
Definition: b2_math.h:41
b2RopeBend::i1
int32 i1
Definition: b2_rope.cpp:40
b2RopeTuning
Definition: b2_rope.h:50
f
f
b2RopeDef::tuning
b2RopeTuning tuning
Definition: b2_rope.h:97
b2RopeStretch::L
float L
Definition: b2_rope.cpp:32
b2RopeTuning::bendDamping
float bendDamping
Definition: b2_rope.h:74
b2Rope::~b2Rope
~b2Rope()
Definition: b2_rope.cpp:66
b2Atan2
#define b2Atan2(y, x)
Definition: b2_math.h:38
b2Draw::DrawPoint
virtual void DrawPoint(const b2Vec2 &p, float size, const b2Color &color)=0
Draw a point.
b2RopeBend::i2
int32 i2
Definition: b2_rope.cpp:40
b2Rope::m_gravity
b2Vec2 m_gravity
Definition: b2_rope.h:148
b2Draw
Definition: b2_draw.h:48
b2_pi
#define b2_pi
Definition: b2_common.h:41
b2RopeTuning::bendingModel
b2BendingModel bendingModel
Definition: b2_rope.h:67
b2Rope::Step
void Step(float timeStep, int32 iterations, const b2Vec2 &position)
Definition: b2_rope.cpp:244
b2RopeBend
Definition: b2_rope.cpp:38
b2RopeTuning::stretchingModel
b2StretchingModel stretchingModel
Definition: b2_rope.h:66
b2Rope::m_count
int32 m_count
Definition: b2_rope.h:135
b2Rope::SolveStretch_XPBD
void SolveStretch_XPBD(float dt)
Definition: b2_rope.cpp:385
b2RopeBend::invEffectiveMass
float invEffectiveMass
Definition: b2_rope.cpp:42
b2_draw.h
b2Dot
float b2Dot(const b2Vec2 &a, const b2Vec2 &b)
Perform the dot product on two vectors.
Definition: b2_math.h:395
b2Rope::m_stretchCount
int32 m_stretchCount
Definition: b2_rope.h:136
b2Color
Color for debug drawing. Each value has the range [0,1].
Definition: b2_draw.h:30
b2RopeDef::position
b2Vec2 position
Definition: b2_rope.h:92
d
d
b2Rope::m_bendCount
int32 m_bendCount
Definition: b2_rope.h:137
b2Rope::m_position
b2Vec2 m_position
Definition: b2_rope.h:133
b2Rope::SetTuning
void SetTuning(const b2RopeTuning &tuning)
Definition: b2_rope.cpp:187
b2Vec2::LengthSquared
float LengthSquared() const
Definition: b2_math.h:96
b2RopeBend::invMass2
float invMass2
Definition: b2_rope.cpp:41
b2_pbdStretchingModel
@ b2_pbdStretchingModel
Definition: b2_rope.h:35
b2Rope::SolveBend_PBD_Angle
void SolveBend_PBD_Angle()
Definition: b2_rope.cpp:433
b2RopeStretch::damper
float damper
Definition: b2_rope.cpp:35
b2RopeTuning::stretchStiffness
float stretchStiffness
Definition: b2_rope.h:69
b2Rope::m_stretchConstraints
b2RopeStretch * m_stretchConstraints
Definition: b2_rope.h:139
b2Rope::Create
void Create(const b2RopeDef &def)
Definition: b2_rope.cpp:77
b2RopeBend::L1
float L1
Definition: b2_rope.cpp:44
b2RopeBend::lambda
float lambda
Definition: b2_rope.cpp:43
b2RopeBend::alpha1
float alpha1
Definition: b2_rope.cpp:45
b2Rope::SolveStretch_PBD
void SolveStretch_PBD()
Definition: b2_rope.cpp:354
b2_pbdHeightBendingModel
@ b2_pbdHeightBendingModel
Definition: b2_rope.h:45
b2RopeBend::spring
float spring
Definition: b2_rope.cpp:46
b2_pbdDistanceBendingModel
@ b2_pbdDistanceBendingModel
Definition: b2_rope.h:44
b2RopeStretch::spring
float spring
Definition: b2_rope.cpp:34
b2RopeTuning::damping
float damping
Definition: b2_rope.h:68
b2_xpbdAngleBendingModel
@ b2_xpbdAngleBendingModel
Definition: b2_rope.h:43
b2RopeStretch::invMass2
float invMass2
Definition: b2_rope.cpp:31
int32
signed int int32
Definition: b2_types.h:28
b2RopeTuning::stretchDamping
float stretchDamping
Definition: b2_rope.h:71
b2RopeBend::invMass3
float invMass3
Definition: b2_rope.cpp:41
b2RopeDef::masses
float * masses
Definition: b2_rope.h:95
b2Free
void b2Free(void *mem)
If you implement b2Alloc, you should also implement this function.
Definition: b2_settings.h:106
b2RopeStretch::lambda
float lambda
Definition: b2_rope.cpp:33
b2RopeBend::damper
float damper
Definition: b2_rope.cpp:47
b2RopeStretch::i2
int32 i2
Definition: b2_rope.cpp:30
b2_springAngleBendingModel
@ b2_springAngleBendingModel
Definition: b2_rope.h:41
b2RopeTuning::fixedEffectiveMass
bool fixedEffectiveMass
Definition: b2_rope.h:76
b2Assert
#define b2Assert(A)
Definition: b2_common.h:37
b2RopeTuning::bendHertz
float bendHertz
Definition: b2_rope.h:73
b2RopeTuning::stretchHertz
float stretchHertz
Definition: b2_rope.h:70
b2Rope::m_ps
b2Vec2 * m_ps
Definition: b2_rope.h:143
b2Rope::m_bendConstraints
b2RopeBend * m_bendConstraints
Definition: b2_rope.h:140
b2Rope::Reset
void Reset(const b2Vec2 &position)
Definition: b2_rope.cpp:332
b2Rope::ApplyBendForces
void ApplyBendForces(float dt)
Definition: b2_rope.cpp:592
b2Rope::m_invMasses
float * m_invMasses
Definition: b2_rope.h:147
b2Rope::m_tuning
b2RopeTuning m_tuning
Definition: b2_rope.h:150
b2Rope::m_p0s
b2Vec2 * m_p0s
Definition: b2_rope.h:144


mvsim
Author(s):
autogenerated on Wed May 28 2025 02:13:07