chipmunk 5.3.4.5 → 6.1.3.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
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
  }