chipmunk 5.3.4.5 → 6.1.3.0.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. data/ext/chipmunk/chipmunk.c +199 -28
  2. data/ext/chipmunk/chipmunk.h +123 -68
  3. data/ext/chipmunk/chipmunk_ffi.h +129 -11
  4. data/ext/chipmunk/chipmunk_private.h +232 -16
  5. data/ext/chipmunk/chipmunk_types.h +94 -30
  6. data/ext/chipmunk/chipmunk_unsafe.h +12 -3
  7. data/ext/chipmunk/constraints/cpConstraint.h +90 -34
  8. data/ext/chipmunk/{cpDampedRotarySpring.h → constraints/cpDampedRotarySpring.h} +18 -8
  9. data/ext/chipmunk/{cpDampedSpring.h → constraints/cpDampedSpring.h} +27 -16
  10. data/ext/chipmunk/constraints/cpGearJoint.h +17 -7
  11. data/ext/chipmunk/constraints/cpGrooveJoint.h +19 -10
  12. data/ext/chipmunk/constraints/cpPinJoint.h +17 -8
  13. data/ext/chipmunk/constraints/cpPivotJoint.h +18 -9
  14. data/ext/chipmunk/constraints/cpRatchetJoint.h +17 -8
  15. data/ext/chipmunk/constraints/cpRotaryLimitJoint.h +16 -7
  16. data/ext/chipmunk/{cpSimpleMotor.h → constraints/cpSimpleMotor.h} +15 -6
  17. data/ext/chipmunk/constraints/cpSlideJoint.h +18 -9
  18. data/ext/chipmunk/constraints/util.h +36 -44
  19. data/ext/chipmunk/cpArbiter.c +159 -94
  20. data/ext/chipmunk/cpArbiter.h +135 -129
  21. data/ext/chipmunk/cpArray.c +37 -56
  22. data/ext/chipmunk/cpBB.c +1 -12
  23. data/ext/chipmunk/cpBB.h +80 -18
  24. data/ext/chipmunk/cpBBTree.c +891 -0
  25. data/ext/chipmunk/cpBody.c +185 -47
  26. data/ext/chipmunk/cpBody.h +156 -124
  27. data/ext/chipmunk/cpCollision.c +126 -115
  28. data/ext/chipmunk/cpConstraint.c +10 -6
  29. data/ext/chipmunk/cpDampedRotarySpring.c +26 -17
  30. data/ext/chipmunk/cpDampedSpring.c +25 -18
  31. data/ext/chipmunk/cpGearJoint.c +23 -17
  32. data/ext/chipmunk/cpGrooveJoint.c +26 -22
  33. data/ext/chipmunk/cpHashSet.c +51 -51
  34. data/ext/chipmunk/cpPinJoint.c +26 -19
  35. data/ext/chipmunk/cpPivotJoint.c +23 -19
  36. data/ext/chipmunk/cpPolyShape.c +93 -69
  37. data/ext/chipmunk/cpPolyShape.h +33 -69
  38. data/ext/chipmunk/cpRatchetJoint.c +26 -21
  39. data/ext/chipmunk/cpRotaryLimitJoint.c +28 -22
  40. data/ext/chipmunk/cpShape.c +122 -133
  41. data/ext/chipmunk/cpShape.h +146 -95
  42. data/ext/chipmunk/cpSimpleMotor.c +24 -17
  43. data/ext/chipmunk/cpSlideJoint.c +28 -26
  44. data/ext/chipmunk/cpSpace.c +251 -196
  45. data/ext/chipmunk/cpSpace.h +173 -103
  46. data/ext/chipmunk/cpSpaceComponent.c +236 -159
  47. data/ext/chipmunk/cpSpaceHash.c +259 -159
  48. data/ext/chipmunk/cpSpaceQuery.c +127 -59
  49. data/ext/chipmunk/cpSpaceStep.c +235 -197
  50. data/ext/chipmunk/cpSpatialIndex.c +69 -0
  51. data/ext/chipmunk/cpSpatialIndex.h +227 -0
  52. data/ext/chipmunk/cpSweep1D.c +254 -0
  53. data/ext/chipmunk/cpVect.c +11 -26
  54. data/ext/chipmunk/cpVect.h +76 -71
  55. data/ext/chipmunk/extconf.rb +4 -31
  56. data/ext/chipmunk/prime.h +1 -1
  57. data/ext/chipmunk/rb_chipmunk.c +36 -45
  58. data/ext/chipmunk/rb_chipmunk.h +6 -3
  59. data/ext/chipmunk/rb_cpArbiter.c +2 -2
  60. data/ext/chipmunk/rb_cpBB.c +116 -35
  61. data/ext/chipmunk/rb_cpBody.c +5 -12
  62. data/ext/chipmunk/rb_cpConstraint.c +144 -9
  63. data/ext/chipmunk/rb_cpShape.c +69 -78
  64. data/ext/chipmunk/rb_cpSpace.c +81 -76
  65. metadata +61 -61
  66. data/LICENSE +0 -22
  67. data/README +0 -110
  68. data/Rakefile +0 -102
  69. data/ext/chipmunk/cpArray.h +0 -49
  70. data/ext/chipmunk/cpCollision.h +0 -28
  71. data/ext/chipmunk/cpHashSet.h +0 -82
  72. data/ext/chipmunk/cpSpaceHash.h +0 -110
  73. data/lib/chipmunk.rb +0 -194
@@ -19,8 +19,12 @@
19
19
  * SOFTWARE.
20
20
  */
21
21
 
22
- const cpConstraintClass *cpRatchetJointGetClass();
22
+ /// @defgroup cpRatchetJoint cpRatchetJoint
23
+ /// @{
23
24
 
25
+ const cpConstraintClass *cpRatchetJointGetClass(void);
26
+
27
+ /// @private
24
28
  typedef struct cpRatchetJoint {
25
29
  cpConstraint constraint;
26
30
  cpFloat angle, phase, ratchet;
@@ -28,13 +32,18 @@ typedef struct cpRatchetJoint {
28
32
  cpFloat iSum;
29
33
 
30
34
  cpFloat bias;
31
- cpFloat jAcc, jMax;
35
+ cpFloat jAcc;
32
36
  } cpRatchetJoint;
33
37
 
34
- cpRatchetJoint *cpRatchetJointAlloc(void);
35
- cpRatchetJoint *cpRatchetJointInit(cpRatchetJoint *joint, cpBody *a, cpBody *b, cpFloat phase, cpFloat ratchet);
36
- cpConstraint *cpRatchetJointNew(cpBody *a, cpBody *b, cpFloat phase, cpFloat ratchet);
38
+ /// Allocate a ratchet joint.
39
+ cpRatchetJoint* cpRatchetJointAlloc(void);
40
+ /// Initialize a ratched joint.
41
+ cpRatchetJoint* cpRatchetJointInit(cpRatchetJoint *joint, cpBody *a, cpBody *b, cpFloat phase, cpFloat ratchet);
42
+ /// Allocate and initialize a ratchet joint.
43
+ cpConstraint* cpRatchetJointNew(cpBody *a, cpBody *b, cpFloat phase, cpFloat ratchet);
44
+
45
+ CP_DefineConstraintProperty(cpRatchetJoint, cpFloat, angle, Angle)
46
+ CP_DefineConstraintProperty(cpRatchetJoint, cpFloat, phase, Phase)
47
+ CP_DefineConstraintProperty(cpRatchetJoint, cpFloat, ratchet, Ratchet)
37
48
 
38
- CP_DefineConstraintProperty(cpRatchetJoint, cpFloat, angle, Angle);
39
- CP_DefineConstraintProperty(cpRatchetJoint, cpFloat, phase, Phase);
40
- CP_DefineConstraintProperty(cpRatchetJoint, cpFloat, ratchet, Ratchet);
49
+ /// @}
@@ -19,8 +19,12 @@
19
19
  * SOFTWARE.
20
20
  */
21
21
 
22
- const cpConstraintClass *cpRotaryLimitJointGetClass();
22
+ /// @defgroup cpRotaryLimitJoint cpRotaryLimitJoint
23
+ /// @{
23
24
 
25
+ const cpConstraintClass *cpRotaryLimitJointGetClass(void);
26
+
27
+ /// @private
24
28
  typedef struct cpRotaryLimitJoint {
25
29
  cpConstraint constraint;
26
30
  cpFloat min, max;
@@ -28,12 +32,17 @@ typedef struct cpRotaryLimitJoint {
28
32
  cpFloat iSum;
29
33
 
30
34
  cpFloat bias;
31
- cpFloat jAcc, jMax;
35
+ cpFloat jAcc;
32
36
  } cpRotaryLimitJoint;
33
37
 
34
- cpRotaryLimitJoint *cpRotaryLimitJointAlloc(void);
35
- cpRotaryLimitJoint *cpRotaryLimitJointInit(cpRotaryLimitJoint *joint, cpBody *a, cpBody *b, cpFloat min, cpFloat max);
36
- cpConstraint *cpRotaryLimitJointNew(cpBody *a, cpBody *b, cpFloat min, cpFloat max);
38
+ /// Allocate a damped rotary limit joint.
39
+ cpRotaryLimitJoint* cpRotaryLimitJointAlloc(void);
40
+ /// Initialize a damped rotary limit joint.
41
+ cpRotaryLimitJoint* cpRotaryLimitJointInit(cpRotaryLimitJoint *joint, cpBody *a, cpBody *b, cpFloat min, cpFloat max);
42
+ /// Allocate and initialize a damped rotary limit joint.
43
+ cpConstraint* cpRotaryLimitJointNew(cpBody *a, cpBody *b, cpFloat min, cpFloat max);
44
+
45
+ CP_DefineConstraintProperty(cpRotaryLimitJoint, cpFloat, min, Min)
46
+ CP_DefineConstraintProperty(cpRotaryLimitJoint, cpFloat, max, Max)
37
47
 
38
- CP_DefineConstraintProperty(cpRotaryLimitJoint, cpFloat, min, Min);
39
- CP_DefineConstraintProperty(cpRotaryLimitJoint, cpFloat, max, Max);
48
+ /// @}
@@ -19,19 +19,28 @@
19
19
  * SOFTWARE.
20
20
  */
21
21
 
22
- const cpConstraintClass *cpSimpleMotorGetClass();
22
+ /// @defgroup cpSimpleMotor cpSimpleMotor
23
+ /// @{
23
24
 
25
+ const cpConstraintClass *cpSimpleMotorGetClass(void);
26
+
27
+ /// @private
24
28
  typedef struct cpSimpleMotor {
25
29
  cpConstraint constraint;
26
30
  cpFloat rate;
27
31
 
28
32
  cpFloat iSum;
29
33
 
30
- cpFloat jAcc, jMax;
34
+ cpFloat jAcc;
31
35
  } cpSimpleMotor;
32
36
 
33
- cpSimpleMotor *cpSimpleMotorAlloc(void);
34
- cpSimpleMotor *cpSimpleMotorInit(cpSimpleMotor *joint, cpBody *a, cpBody *b, cpFloat rate);
35
- cpConstraint *cpSimpleMotorNew(cpBody *a, cpBody *b, cpFloat rate);
37
+ /// Allocate a simple motor.
38
+ cpSimpleMotor* cpSimpleMotorAlloc(void);
39
+ /// initialize a simple motor.
40
+ cpSimpleMotor* cpSimpleMotorInit(cpSimpleMotor *joint, cpBody *a, cpBody *b, cpFloat rate);
41
+ /// Allocate and initialize a simple motor.
42
+ cpConstraint* cpSimpleMotorNew(cpBody *a, cpBody *b, cpFloat rate);
43
+
44
+ CP_DefineConstraintProperty(cpSimpleMotor, cpFloat, rate, Rate)
36
45
 
37
- CP_DefineConstraintProperty(cpSimpleMotor, cpFloat, rate, Rate);
46
+ /// @}
@@ -19,8 +19,12 @@
19
19
  * SOFTWARE.
20
20
  */
21
21
 
22
- const cpConstraintClass *cpSlideJointGetClass();
22
+ /// @defgroup cpSlideJoint cpSlideJoint
23
+ /// @{
23
24
 
25
+ const cpConstraintClass *cpSlideJointGetClass(void);
26
+
27
+ /// @private
24
28
  typedef struct cpSlideJoint {
25
29
  cpConstraint constraint;
26
30
  cpVect anchr1, anchr2;
@@ -30,15 +34,20 @@ typedef struct cpSlideJoint {
30
34
  cpVect n;
31
35
  cpFloat nMass;
32
36
 
33
- cpFloat jnAcc, jnMax;
37
+ cpFloat jnAcc;
34
38
  cpFloat bias;
35
39
  } cpSlideJoint;
36
40
 
37
- cpSlideJoint *cpSlideJointAlloc(void);
38
- cpSlideJoint *cpSlideJointInit(cpSlideJoint *joint, cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat min, cpFloat max);
39
- cpConstraint *cpSlideJointNew(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat min, cpFloat max);
41
+ /// Allocate a slide joint.
42
+ cpSlideJoint* cpSlideJointAlloc(void);
43
+ /// Initialize a slide joint.
44
+ cpSlideJoint* cpSlideJointInit(cpSlideJoint *joint, cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat min, cpFloat max);
45
+ /// Allocate and initialize a slide joint.
46
+ cpConstraint* cpSlideJointNew(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat min, cpFloat max);
47
+
48
+ CP_DefineConstraintProperty(cpSlideJoint, cpVect, anchr1, Anchr1)
49
+ CP_DefineConstraintProperty(cpSlideJoint, cpVect, anchr2, Anchr2)
50
+ CP_DefineConstraintProperty(cpSlideJoint, cpFloat, min, Min)
51
+ CP_DefineConstraintProperty(cpSlideJoint, cpFloat, max, Max)
40
52
 
41
- CP_DefineConstraintProperty(cpSlideJoint, cpVect, anchr1, Anchr1);
42
- CP_DefineConstraintProperty(cpSlideJoint, cpVect, anchr2, Anchr2);
43
- CP_DefineConstraintProperty(cpSlideJoint, cpFloat, min, Min);
44
- CP_DefineConstraintProperty(cpSlideJoint, cpFloat, max, Max);
53
+ /// @}
@@ -19,22 +19,13 @@
19
19
  * SOFTWARE.
20
20
  */
21
21
 
22
- #define CP_DefineClassGetter(t) const cpConstraintClass * t##GetClass(){return (cpConstraintClass *)&klass;}
22
+ // These are utility routines to use when creating custom constraints.
23
+ // I'm not sure if this should be part of the private API or not.
24
+ // I should probably clean up the naming conventions if it is...
23
25
 
24
- void cpConstraintInit(cpConstraint *constraint, const cpConstraintClass *klass, cpBody *a, cpBody *b);
25
-
26
- #define J_MAX(constraint, dt) (((cpConstraint *)constraint)->maxForce*(dt))
26
+ #define CP_DefineClassGetter(t) const cpConstraintClass * t##GetClass(void){return (cpConstraintClass *)&klass;}
27
27
 
28
- // Get valid body pointers and exit early if the bodies are idle
29
- #define CONSTRAINT_BEGIN(constraint, a_var, b_var) \
30
- cpBody *a_var, *b_var; { \
31
- a_var = ((cpConstraint *)constraint)->a; \
32
- b_var = ((cpConstraint *)constraint)->b; \
33
- if( \
34
- (cpBodyIsSleeping(a_var) || cpBodyIsStatic(a_var)) && \
35
- (cpBodyIsSleeping(b_var) || cpBodyIsStatic(b_var)) \
36
- ) return; \
37
- }
28
+ void cpConstraintInit(cpConstraint *constraint, const cpConstraintClass *klass, cpBody *a, cpBody *b);
38
29
 
39
30
  static inline cpVect
40
31
  relative_velocity(cpBody *a, cpBody *b, cpVect r1, cpVect r2){
@@ -49,18 +40,24 @@ normal_relative_velocity(cpBody *a, cpBody *b, cpVect r1, cpVect r2, cpVect n){
49
40
  return cpvdot(relative_velocity(a, b, r1, r2), n);
50
41
  }
51
42
 
43
+ static inline void
44
+ apply_impulse(cpBody *body, cpVect j, cpVect r){
45
+ body->v = cpvadd(body->v, cpvmult(j, body->m_inv));
46
+ body->w += body->i_inv*cpvcross(r, j);
47
+ }
48
+
52
49
  static inline void
53
50
  apply_impulses(cpBody *a , cpBody *b, cpVect r1, cpVect r2, cpVect j)
54
51
  {
55
- cpBodyApplyImpulse(a, cpvneg(j), r1);
56
- cpBodyApplyImpulse(b, j, r2);
52
+ apply_impulse(a, cpvneg(j), r1);
53
+ apply_impulse(b, j, r2);
57
54
  }
58
55
 
59
56
  static inline void
60
57
  apply_bias_impulse(cpBody *body, cpVect j, cpVect r)
61
58
  {
62
- body->v_bias = cpvadd(body->v_bias, cpvmult(j, body->m_inv));
63
- body->w_bias += body->i_inv*cpvcross(r, j);
59
+ body->CP_PRIVATE(v_bias) = cpvadd(body->CP_PRIVATE(v_bias), cpvmult(j, body->m_inv));
60
+ body->CP_PRIVATE(w_bias) += body->i_inv*cpvcross(r, j);
64
61
  }
65
62
 
66
63
  static inline void
@@ -70,37 +67,30 @@ apply_bias_impulses(cpBody *a , cpBody *b, cpVect r1, cpVect r2, cpVect j)
70
67
  apply_bias_impulse(b, j, r2);
71
68
  }
72
69
 
73
- static inline cpVect
74
- clamp_vect(cpVect v, cpFloat len)
70
+ static inline cpFloat
71
+ k_scalar_body(cpBody *body, cpVect r, cpVect n)
75
72
  {
76
- return cpvclamp(v, len);
77
- // return (cpvdot(v,v) > len*len) ? cpvmult(cpvnormalize(v), len) : v;
73
+ cpFloat rcn = cpvcross(r, n);
74
+ return body->m_inv + body->i_inv*rcn*rcn;
78
75
  }
79
76
 
80
77
  static inline cpFloat
81
78
  k_scalar(cpBody *a, cpBody *b, cpVect r1, cpVect r2, cpVect n)
82
79
  {
83
- cpFloat mass_sum = a->m_inv + b->m_inv;
84
- cpFloat r1cn = cpvcross(r1, n);
85
- cpFloat r2cn = cpvcross(r2, n);
86
-
87
- cpFloat value = mass_sum + a->i_inv*r1cn*r1cn + b->i_inv*r2cn*r2cn;
88
- cpAssert(value != 0.0, "Unsolvable collision or constraint.");
80
+ cpFloat value = k_scalar_body(a, r1, n) + k_scalar_body(b, r2, n);
81
+ cpAssertSoft(value != 0.0, "Unsolvable collision or constraint.");
89
82
 
90
83
  return value;
91
84
  }
92
85
 
93
- static inline void
94
- k_tensor(cpBody *a, cpBody *b, cpVect r1, cpVect r2, cpVect *k1, cpVect *k2)
86
+ static inline cpMat2x2
87
+ k_tensor(cpBody *a, cpBody *b, cpVect r1, cpVect r2)
95
88
  {
96
- // calculate mass matrix
97
- // If I wasn't lazy and wrote a proper matrix class, this wouldn't be so gross...
98
- cpFloat k11, k12, k21, k22;
99
89
  cpFloat m_sum = a->m_inv + b->m_inv;
100
90
 
101
- // start with I*m_sum
102
- k11 = m_sum; k12 = 0.0f;
103
- k21 = 0.0f; k22 = m_sum;
91
+ // start with Identity*m_sum
92
+ cpFloat k11 = m_sum, k12 = 0.0f;
93
+ cpFloat k21 = 0.0f, k22 = m_sum;
104
94
 
105
95
  // add the influence from r1
106
96
  cpFloat a_i_inv = a->i_inv;
@@ -119,16 +109,18 @@ k_tensor(cpBody *a, cpBody *b, cpVect r1, cpVect r2, cpVect *k1, cpVect *k2)
119
109
  k21 += r2nxy; k22 += r2xsq;
120
110
 
121
111
  // invert
122
- cpFloat determinant = k11*k22 - k12*k21;
123
- cpAssert(determinant != 0.0, "Unsolvable constraint.");
112
+ cpFloat det = k11*k22 - k12*k21;
113
+ cpAssertSoft(det != 0.0, "Unsolvable constraint.");
124
114
 
125
- cpFloat det_inv = 1.0f/determinant;
126
- *k1 = cpv( k22*det_inv, -k12*det_inv);
127
- *k2 = cpv(-k21*det_inv, k11*det_inv);
115
+ cpFloat det_inv = 1.0f/det;
116
+ return cpMat2x2New(
117
+ k22*det_inv, -k12*det_inv,
118
+ -k21*det_inv, k11*det_inv
119
+ );
128
120
  }
129
121
 
130
- static inline cpVect
131
- mult_k(cpVect vr, cpVect k1, cpVect k2)
122
+ static inline cpFloat
123
+ bias_coef(cpFloat errorBias, cpFloat dt)
132
124
  {
133
- return cpv(cpvdot(vr, k1), cpvdot(vr, k2));
125
+ return 1.0f - cpfpow(errorBias, dt);
134
126
  }
@@ -18,15 +18,10 @@
18
18
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
19
  * SOFTWARE.
20
20
  */
21
-
22
- #include <stdlib.h>
23
21
 
24
22
  #include "chipmunk_private.h"
25
23
  #include "constraints/util.h"
26
24
 
27
- cpFloat cp_bias_coef = 0.1f;
28
- cpFloat cp_collision_slop = 0.1f;
29
-
30
25
  cpContact*
31
26
  cpContactInit(cpContact *con, cpVect p, cpVect n, cpFloat dist, cpHashValue hash)
32
27
  {
@@ -43,62 +38,157 @@ cpContactInit(cpContact *con, cpVect p, cpVect n, cpFloat dist, cpHashValue hash
43
38
  return con;
44
39
  }
45
40
 
41
+ // TODO make this generic so I can reuse it for constraints also.
42
+ static inline void
43
+ unthreadHelper(cpArbiter *arb, cpBody *body)
44
+ {
45
+ struct cpArbiterThread *thread = cpArbiterThreadForBody(arb, body);
46
+ cpArbiter *prev = thread->prev;
47
+ cpArbiter *next = thread->next;
48
+
49
+ if(prev){
50
+ cpArbiterThreadForBody(prev, body)->next = next;
51
+ } else if(body->arbiterList == arb) {
52
+ // IFF prev is NULL and body->arbiterList == arb, is arb at the head of the list.
53
+ // This function may be called for an arbiter that was never in a list.
54
+ // In that case, we need to protect it from wiping out the body->arbiterList pointer.
55
+ body->arbiterList = next;
56
+ }
57
+
58
+ if(next) cpArbiterThreadForBody(next, body)->prev = prev;
59
+
60
+ thread->prev = NULL;
61
+ thread->next = NULL;
62
+ }
63
+
64
+ void
65
+ cpArbiterUnthread(cpArbiter *arb)
66
+ {
67
+ unthreadHelper(arb, arb->body_a);
68
+ unthreadHelper(arb, arb->body_b);
69
+ }
70
+
71
+ cpBool cpArbiterIsFirstContact(const cpArbiter *arb)
72
+ {
73
+ return arb->CP_PRIVATE(state) == cpArbiterStateFirstColl;
74
+ }
75
+
76
+ int cpArbiterGetCount(const cpArbiter *arb)
77
+ {
78
+ // Return 0 contacts if we are in a separate callback.
79
+ return (arb->CP_PRIVATE(state) != cpArbiterStateCached ? arb->CP_PRIVATE(numContacts) : 0);
80
+ }
81
+
82
+ cpVect
83
+ cpArbiterGetNormal(const cpArbiter *arb, int i)
84
+ {
85
+ cpAssertHard(0 <= i && i < cpArbiterGetCount(arb), "Index error: The specified contact index is invalid for this arbiter");
86
+
87
+ cpVect n = arb->contacts[i].n;
88
+ return arb->swappedColl ? cpvneg(n) : n;
89
+ }
90
+
91
+ cpVect
92
+ cpArbiterGetPoint(const cpArbiter *arb, int i)
93
+ {
94
+ cpAssertHard(0 <= i && i < cpArbiterGetCount(arb), "Index error: The specified contact index is invalid for this arbiter");
95
+
96
+ return arb->CP_PRIVATE(contacts)[i].CP_PRIVATE(p);
97
+ }
98
+
99
+ cpFloat
100
+ cpArbiterGetDepth(const cpArbiter *arb, int i)
101
+ {
102
+ cpAssertHard(0 <= i && i < cpArbiterGetCount(arb), "Index error: The specified contact index is invalid for this arbiter");
103
+
104
+ return arb->CP_PRIVATE(contacts)[i].CP_PRIVATE(dist);
105
+ }
106
+
107
+ cpContactPointSet
108
+ cpArbiterGetContactPointSet(const cpArbiter *arb)
109
+ {
110
+ cpContactPointSet set;
111
+ set.count = cpArbiterGetCount(arb);
112
+
113
+ int i;
114
+ for(i=0; i<set.count; i++){
115
+ set.points[i].point = arb->CP_PRIVATE(contacts)[i].CP_PRIVATE(p);
116
+ set.points[i].normal = arb->CP_PRIVATE(contacts)[i].CP_PRIVATE(n);
117
+ set.points[i].dist = arb->CP_PRIVATE(contacts)[i].CP_PRIVATE(dist);
118
+ }
119
+
120
+ return set;
121
+ }
122
+
123
+
46
124
  cpVect
47
- cpArbiterTotalImpulse(cpArbiter *arb)
125
+ cpArbiterTotalImpulse(const cpArbiter *arb)
48
126
  {
49
127
  cpContact *contacts = arb->contacts;
50
128
  cpVect sum = cpvzero;
51
129
 
52
- for(int i=0, count=arb->numContacts; i<count; i++){
130
+ for(int i=0, count=cpArbiterGetCount(arb); i<count; i++){
53
131
  cpContact *con = &contacts[i];
54
132
  sum = cpvadd(sum, cpvmult(con->n, con->jnAcc));
55
133
  }
56
-
57
- return sum;
134
+
135
+ return (arb->swappedColl ? sum : cpvneg(sum));
58
136
  }
59
137
 
60
138
  cpVect
61
- cpArbiterTotalImpulseWithFriction(cpArbiter *arb)
139
+ cpArbiterTotalImpulseWithFriction(const cpArbiter *arb)
62
140
  {
63
141
  cpContact *contacts = arb->contacts;
64
142
  cpVect sum = cpvzero;
65
143
 
66
- for(int i=0, count=arb->numContacts; i<count; i++){
144
+ for(int i=0, count=cpArbiterGetCount(arb); i<count; i++){
67
145
  cpContact *con = &contacts[i];
68
146
  sum = cpvadd(sum, cpvrotate(con->n, cpv(con->jnAcc, con->jtAcc)));
69
147
  }
70
148
 
71
- return sum;
149
+ return (arb->swappedColl ? sum : cpvneg(sum));
72
150
  }
73
151
 
74
152
  cpFloat
75
- cpContactsEstimateCrushingImpulse(cpContact *contacts, int numContacts)
153
+ cpArbiterTotalKE(const cpArbiter *arb)
76
154
  {
77
- cpFloat fsum = 0.0f;
78
- cpVect vsum = cpvzero;
155
+ cpFloat eCoef = (1 - arb->e)/(1 + arb->e);
156
+ cpFloat sum = 0.0;
79
157
 
80
- for(int i=0; i<numContacts; i++){
158
+ cpContact *contacts = arb->contacts;
159
+ for(int i=0, count=cpArbiterGetCount(arb); i<count; i++){
81
160
  cpContact *con = &contacts[i];
82
- cpVect j = cpvrotate(con->n, cpv(con->jnAcc, con->jtAcc));
161
+ cpFloat jnAcc = con->jnAcc;
162
+ cpFloat jtAcc = con->jtAcc;
83
163
 
84
- fsum += cpvlength(j);
85
- vsum = cpvadd(vsum, j);
164
+ sum += eCoef*jnAcc*jnAcc/con->nMass + jtAcc*jtAcc/con->tMass;
86
165
  }
87
166
 
88
- cpFloat vmag = cpvlength(vsum);
89
- return (1.0f - vmag/fsum);
167
+ return sum;
90
168
  }
91
169
 
170
+ //cpFloat
171
+ //cpContactsEstimateCrushingImpulse(cpContact *contacts, int numContacts)
172
+ //{
173
+ // cpFloat fsum = 0.0f;
174
+ // cpVect vsum = cpvzero;
175
+ //
176
+ // for(int i=0; i<numContacts; i++){
177
+ // cpContact *con = &contacts[i];
178
+ // cpVect j = cpvrotate(con->n, cpv(con->jnAcc, con->jtAcc));
179
+ //
180
+ // fsum += cpvlength(j);
181
+ // vsum = cpvadd(vsum, j);
182
+ // }
183
+ //
184
+ // cpFloat vmag = cpvlength(vsum);
185
+ // return (1.0f - vmag/fsum);
186
+ //}
187
+
92
188
  void
93
189
  cpArbiterIgnore(cpArbiter *arb)
94
190
  {
95
- arb->state = cpArbiterStateIgnore ;
96
- }
97
-
98
- cpArbiter*
99
- cpArbiterAlloc(void)
100
- {
101
- return (cpArbiter *)cpcalloc(1, sizeof(cpArbiter));
191
+ arb->state = cpArbiterStateIgnore;
102
192
  }
103
193
 
104
194
  cpArbiter*
@@ -114,41 +204,27 @@ cpArbiterInit(cpArbiter *arb, cpShape *a, cpShape *b)
114
204
  arb->numContacts = 0;
115
205
  arb->contacts = NULL;
116
206
 
117
- arb->a = a;
118
- arb->b = b;
207
+ arb->a = a; arb->body_a = a->body;
208
+ arb->b = b; arb->body_b = b->body;
209
+
210
+ arb->thread_a.next = NULL;
211
+ arb->thread_b.next = NULL;
212
+ arb->thread_a.prev = NULL;
213
+ arb->thread_b.prev = NULL;
119
214
 
120
215
  arb->stamp = 0;
121
216
  arb->state = cpArbiterStateFirstColl;
122
217
 
218
+ arb->data = NULL;
219
+
123
220
  return arb;
124
221
  }
125
222
 
126
- cpArbiter*
127
- cpArbiterNew(cpShape *a, cpShape *b)
128
- {
129
- return cpArbiterInit(cpArbiterAlloc(), a, b);
130
- }
131
-
132
- void
133
- cpArbiterDestroy(cpArbiter *arb)
134
- {
135
- // if(arb->contacts) cpfree(arb->contacts);
136
- }
137
-
138
- void
139
- cpArbiterFree(cpArbiter *arb)
140
- {
141
- if(arb){
142
- cpArbiterDestroy(arb);
143
- cpfree(arb);
144
- }
145
- }
146
-
147
223
  void
148
224
  cpArbiterUpdate(cpArbiter *arb, cpContact *contacts, int numContacts, cpCollisionHandler *handler, cpShape *a, cpShape *b)
149
225
  {
150
226
  // Arbiters without contact data may exist if a collision function rejected the collision.
151
- if(arb->contacts){
227
+ if(arb->numContacts > 0){
152
228
  // Iterate over the possible pairs to look for hash value matches.
153
229
  for(int i=0; i<arb->numContacts; i++){
154
230
  cpContact *old = &arb->contacts[i];
@@ -177,18 +253,18 @@ cpArbiterUpdate(cpArbiter *arb, cpContact *contacts, int numContacts, cpCollisio
177
253
  arb->surface_vr = cpvsub(a->surface_v, b->surface_v);
178
254
 
179
255
  // For collisions between two similar primitive types, the order could have been swapped.
180
- arb->a = a;
181
- arb->b = b;
256
+ arb->a = a; arb->body_a = a->body;
257
+ arb->b = b; arb->body_b = b->body;
182
258
 
183
259
  // mark it as new if it's been cached
184
260
  if(arb->state == cpArbiterStateCached) arb->state = cpArbiterStateFirstColl;
185
261
  }
186
262
 
187
263
  void
188
- cpArbiterPreStep(cpArbiter *arb, cpFloat dt_inv)
264
+ cpArbiterPreStep(cpArbiter *arb, cpFloat dt, cpFloat slop, cpFloat bias)
189
265
  {
190
- cpBody *a = arb->a->body;
191
- cpBody *b = arb->b->body;
266
+ cpBody *a = arb->body_a;
267
+ cpBody *b = arb->body_b;
192
268
 
193
269
  for(int i=0; i<arb->numContacts; i++){
194
270
  cpContact *con = &arb->contacts[i];
@@ -202,79 +278,68 @@ cpArbiterPreStep(cpArbiter *arb, cpFloat dt_inv)
202
278
  con->tMass = 1.0f/k_scalar(a, b, con->r1, con->r2, cpvperp(con->n));
203
279
 
204
280
  // Calculate the target bias velocity.
205
- con->bias = -cp_bias_coef*dt_inv*cpfmin(0.0f, con->dist + cp_collision_slop);
281
+ con->bias = -bias*cpfmin(0.0f, con->dist + slop)/dt;
206
282
  con->jBias = 0.0f;
207
283
 
208
284
  // Calculate the target bounce velocity.
209
- con->bounce = normal_relative_velocity(a, b, con->r1, con->r2, con->n)*arb->e;//cpvdot(con->n, cpvsub(v2, v1))*e;
285
+ con->bounce = normal_relative_velocity(a, b, con->r1, con->r2, con->n)*arb->e;
210
286
  }
211
287
  }
212
288
 
213
289
  void
214
- cpArbiterApplyCachedImpulse(cpArbiter *arb)
290
+ cpArbiterApplyCachedImpulse(cpArbiter *arb, cpFloat dt_coef)
215
291
  {
216
- cpShape *shapea = arb->a;
217
- cpShape *shapeb = arb->b;
218
-
219
- arb->u = shapea->u * shapeb->u;
220
- arb->surface_vr = cpvsub(shapeb->surface_v, shapea->surface_v);
221
-
222
- cpBody *a = shapea->body;
223
- cpBody *b = shapeb->body;
292
+ if(cpArbiterIsFirstContact(arb)) return;
293
+
294
+ cpBody *a = arb->body_a;
295
+ cpBody *b = arb->body_b;
224
296
 
225
297
  for(int i=0; i<arb->numContacts; i++){
226
298
  cpContact *con = &arb->contacts[i];
227
- apply_impulses(a, b, con->r1, con->r2, cpvrotate(con->n, cpv(con->jnAcc, con->jtAcc)));
299
+ cpVect j = cpvrotate(con->n, cpv(con->jnAcc, con->jtAcc));
300
+ apply_impulses(a, b, con->r1, con->r2, cpvmult(j, dt_coef));
228
301
  }
229
302
  }
230
303
 
304
+ // TODO is it worth splitting velocity/position correction?
305
+
231
306
  void
232
- cpArbiterApplyImpulse(cpArbiter *arb, cpFloat eCoef)
307
+ cpArbiterApplyImpulse(cpArbiter *arb)
233
308
  {
234
- cpBody *a = arb->a->body;
235
- cpBody *b = arb->b->body;
309
+ cpBody *a = arb->body_a;
310
+ cpBody *b = arb->body_b;
311
+ cpVect surface_vr = arb->surface_vr;
312
+ cpFloat friction = arb->u;
236
313
 
237
314
  for(int i=0; i<arb->numContacts; i++){
238
315
  cpContact *con = &arb->contacts[i];
316
+ cpFloat nMass = con->nMass;
239
317
  cpVect n = con->n;
240
318
  cpVect r1 = con->r1;
241
319
  cpVect r2 = con->r2;
242
320
 
243
- // Calculate the relative bias velocities.
244
321
  cpVect vb1 = cpvadd(a->v_bias, cpvmult(cpvperp(r1), a->w_bias));
245
322
  cpVect vb2 = cpvadd(b->v_bias, cpvmult(cpvperp(r2), b->w_bias));
323
+ cpVect vr = relative_velocity(a, b, r1, r2);
324
+
246
325
  cpFloat vbn = cpvdot(cpvsub(vb2, vb1), n);
326
+ cpFloat vrn = cpvdot(vr, n);
327
+ cpFloat vrt = cpvdot(cpvadd(vr, surface_vr), cpvperp(n));
247
328
 
248
- // Calculate and clamp the bias impulse.
249
- cpFloat jbn = (con->bias - vbn)*con->nMass;
329
+ cpFloat jbn = (con->bias - vbn)*nMass;
250
330
  cpFloat jbnOld = con->jBias;
251
331
  con->jBias = cpfmax(jbnOld + jbn, 0.0f);
252
- jbn = con->jBias - jbnOld;
253
332
 
254
- // Apply the bias impulse.
255
- apply_bias_impulses(a, b, r1, r2, cpvmult(n, jbn));
256
-
257
- // Calculate the relative velocity.
258
- cpVect vr = relative_velocity(a, b, r1, r2);
259
- cpFloat vrn = cpvdot(vr, n);
260
-
261
- // Calculate and clamp the normal impulse.
262
- cpFloat jn = -(con->bounce*eCoef + vrn)*con->nMass;
333
+ cpFloat jn = -(con->bounce + vrn)*nMass;
263
334
  cpFloat jnOld = con->jnAcc;
264
335
  con->jnAcc = cpfmax(jnOld + jn, 0.0f);
265
- jn = con->jnAcc - jnOld;
266
-
267
- // Calculate the relative tangent velocity.
268
- cpFloat vrt = cpvdot(cpvadd(vr, arb->surface_vr), cpvperp(n));
269
336
 
270
- // Calculate and clamp the friction impulse.
271
- cpFloat jtMax = arb->u*con->jnAcc;
337
+ cpFloat jtMax = friction*con->jnAcc;
272
338
  cpFloat jt = -vrt*con->tMass;
273
339
  cpFloat jtOld = con->jtAcc;
274
340
  con->jtAcc = cpfclamp(jtOld + jt, -jtMax, jtMax);
275
- jt = con->jtAcc - jtOld;
276
341
 
277
- // Apply the final impulse.
278
- apply_impulses(a, b, r1, r2, cpvrotate(n, cpv(jn, jt)));
342
+ apply_bias_impulses(a, b, r1, r2, cpvmult(n, con->jBias - jbnOld));
343
+ apply_impulses(a, b, r1, r2, cpvrotate(n, cpv(con->jnAcc - jnOld, con->jtAcc - jtOld)));
279
344
  }
280
345
  }