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.
- data/ext/chipmunk/chipmunk.c +199 -28
- data/ext/chipmunk/chipmunk.h +123 -68
- data/ext/chipmunk/chipmunk_ffi.h +129 -11
- data/ext/chipmunk/chipmunk_private.h +232 -16
- data/ext/chipmunk/chipmunk_types.h +94 -30
- data/ext/chipmunk/chipmunk_unsafe.h +12 -3
- data/ext/chipmunk/constraints/cpConstraint.h +90 -34
- data/ext/chipmunk/{cpDampedRotarySpring.h → constraints/cpDampedRotarySpring.h} +18 -8
- data/ext/chipmunk/{cpDampedSpring.h → constraints/cpDampedSpring.h} +27 -16
- data/ext/chipmunk/constraints/cpGearJoint.h +17 -7
- data/ext/chipmunk/constraints/cpGrooveJoint.h +19 -10
- data/ext/chipmunk/constraints/cpPinJoint.h +17 -8
- data/ext/chipmunk/constraints/cpPivotJoint.h +18 -9
- data/ext/chipmunk/constraints/cpRatchetJoint.h +17 -8
- data/ext/chipmunk/constraints/cpRotaryLimitJoint.h +16 -7
- data/ext/chipmunk/{cpSimpleMotor.h → constraints/cpSimpleMotor.h} +15 -6
- data/ext/chipmunk/constraints/cpSlideJoint.h +18 -9
- data/ext/chipmunk/constraints/util.h +36 -44
- data/ext/chipmunk/cpArbiter.c +159 -94
- data/ext/chipmunk/cpArbiter.h +135 -129
- data/ext/chipmunk/cpArray.c +37 -56
- data/ext/chipmunk/cpBB.c +1 -12
- data/ext/chipmunk/cpBB.h +80 -18
- data/ext/chipmunk/cpBBTree.c +891 -0
- data/ext/chipmunk/cpBody.c +185 -47
- data/ext/chipmunk/cpBody.h +156 -124
- data/ext/chipmunk/cpCollision.c +126 -115
- data/ext/chipmunk/cpConstraint.c +10 -6
- data/ext/chipmunk/cpDampedRotarySpring.c +26 -17
- data/ext/chipmunk/cpDampedSpring.c +25 -18
- data/ext/chipmunk/cpGearJoint.c +23 -17
- data/ext/chipmunk/cpGrooveJoint.c +26 -22
- data/ext/chipmunk/cpHashSet.c +51 -51
- data/ext/chipmunk/cpPinJoint.c +26 -19
- data/ext/chipmunk/cpPivotJoint.c +23 -19
- data/ext/chipmunk/cpPolyShape.c +93 -69
- data/ext/chipmunk/cpPolyShape.h +33 -69
- data/ext/chipmunk/cpRatchetJoint.c +26 -21
- data/ext/chipmunk/cpRotaryLimitJoint.c +28 -22
- data/ext/chipmunk/cpShape.c +122 -133
- data/ext/chipmunk/cpShape.h +146 -95
- data/ext/chipmunk/cpSimpleMotor.c +24 -17
- data/ext/chipmunk/cpSlideJoint.c +28 -26
- data/ext/chipmunk/cpSpace.c +251 -196
- data/ext/chipmunk/cpSpace.h +173 -103
- data/ext/chipmunk/cpSpaceComponent.c +236 -159
- data/ext/chipmunk/cpSpaceHash.c +259 -159
- data/ext/chipmunk/cpSpaceQuery.c +127 -59
- data/ext/chipmunk/cpSpaceStep.c +235 -197
- data/ext/chipmunk/cpSpatialIndex.c +69 -0
- data/ext/chipmunk/cpSpatialIndex.h +227 -0
- data/ext/chipmunk/cpSweep1D.c +254 -0
- data/ext/chipmunk/cpVect.c +11 -26
- data/ext/chipmunk/cpVect.h +76 -71
- data/ext/chipmunk/extconf.rb +4 -31
- data/ext/chipmunk/prime.h +1 -1
- data/ext/chipmunk/rb_chipmunk.c +36 -45
- data/ext/chipmunk/rb_chipmunk.h +6 -3
- data/ext/chipmunk/rb_cpArbiter.c +2 -2
- data/ext/chipmunk/rb_cpBB.c +116 -35
- data/ext/chipmunk/rb_cpBody.c +5 -12
- data/ext/chipmunk/rb_cpConstraint.c +144 -9
- data/ext/chipmunk/rb_cpShape.c +69 -78
- data/ext/chipmunk/rb_cpSpace.c +81 -76
- metadata +61 -61
- data/LICENSE +0 -22
- data/README +0 -110
- data/Rakefile +0 -102
- data/ext/chipmunk/cpArray.h +0 -49
- data/ext/chipmunk/cpCollision.h +0 -28
- data/ext/chipmunk/cpHashSet.h +0 -82
- data/ext/chipmunk/cpSpaceHash.h +0 -110
- data/lib/chipmunk.rb +0 -194
@@ -19,8 +19,12 @@
|
|
19
19
|
* SOFTWARE.
|
20
20
|
*/
|
21
21
|
|
22
|
-
|
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
|
35
|
+
cpFloat jAcc;
|
32
36
|
} cpRatchetJoint;
|
33
37
|
|
34
|
-
|
35
|
-
cpRatchetJoint
|
36
|
-
|
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
|
-
|
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
|
-
|
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
|
35
|
+
cpFloat jAcc;
|
32
36
|
} cpRotaryLimitJoint;
|
33
37
|
|
34
|
-
|
35
|
-
cpRotaryLimitJoint
|
36
|
-
|
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
|
-
|
39
|
-
CP_DefineConstraintProperty(cpRotaryLimitJoint, cpFloat, max, Max);
|
48
|
+
/// @}
|
@@ -19,19 +19,28 @@
|
|
19
19
|
* SOFTWARE.
|
20
20
|
*/
|
21
21
|
|
22
|
-
|
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
|
34
|
+
cpFloat jAcc;
|
31
35
|
} cpSimpleMotor;
|
32
36
|
|
33
|
-
|
34
|
-
cpSimpleMotor
|
35
|
-
|
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
|
-
|
46
|
+
/// @}
|
@@ -19,8 +19,12 @@
|
|
19
19
|
* SOFTWARE.
|
20
20
|
*/
|
21
21
|
|
22
|
-
|
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
|
37
|
+
cpFloat jnAcc;
|
34
38
|
cpFloat bias;
|
35
39
|
} cpSlideJoint;
|
36
40
|
|
37
|
-
|
38
|
-
cpSlideJoint
|
39
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
56
|
-
|
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
|
74
|
-
|
70
|
+
static inline cpFloat
|
71
|
+
k_scalar_body(cpBody *body, cpVect r, cpVect n)
|
75
72
|
{
|
76
|
-
|
77
|
-
|
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
|
84
|
-
|
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
|
94
|
-
k_tensor(cpBody *a, cpBody *b, cpVect r1, cpVect r2
|
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
|
102
|
-
k11 = m_sum
|
103
|
-
k21 = 0.0f
|
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
|
123
|
-
|
112
|
+
cpFloat det = k11*k22 - k12*k21;
|
113
|
+
cpAssertSoft(det != 0.0, "Unsolvable constraint.");
|
124
114
|
|
125
|
-
cpFloat det_inv = 1.0f/
|
126
|
-
|
127
|
-
|
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
|
131
|
-
|
122
|
+
static inline cpFloat
|
123
|
+
bias_coef(cpFloat errorBias, cpFloat dt)
|
132
124
|
{
|
133
|
-
return
|
125
|
+
return 1.0f - cpfpow(errorBias, dt);
|
134
126
|
}
|
data/ext/chipmunk/cpArbiter.c
CHANGED
@@ -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
|
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
|
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
|
-
|
153
|
+
cpArbiterTotalKE(const cpArbiter *arb)
|
76
154
|
{
|
77
|
-
cpFloat
|
78
|
-
|
155
|
+
cpFloat eCoef = (1 - arb->e)/(1 + arb->e);
|
156
|
+
cpFloat sum = 0.0;
|
79
157
|
|
80
|
-
|
158
|
+
cpContact *contacts = arb->contacts;
|
159
|
+
for(int i=0, count=cpArbiterGetCount(arb); i<count; i++){
|
81
160
|
cpContact *con = &contacts[i];
|
82
|
-
|
161
|
+
cpFloat jnAcc = con->jnAcc;
|
162
|
+
cpFloat jtAcc = con->jtAcc;
|
83
163
|
|
84
|
-
|
85
|
-
vsum = cpvadd(vsum, j);
|
164
|
+
sum += eCoef*jnAcc*jnAcc/con->nMass + jtAcc*jtAcc/con->tMass;
|
86
165
|
}
|
87
166
|
|
88
|
-
|
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->
|
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
|
264
|
+
cpArbiterPreStep(cpArbiter *arb, cpFloat dt, cpFloat slop, cpFloat bias)
|
189
265
|
{
|
190
|
-
cpBody *a = arb->
|
191
|
-
cpBody *b = arb->
|
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 = -
|
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
|
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
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
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
|
-
|
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
|
307
|
+
cpArbiterApplyImpulse(cpArbiter *arb)
|
233
308
|
{
|
234
|
-
cpBody *a = arb->
|
235
|
-
cpBody *b = arb->
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
278
|
-
apply_impulses(a, b, r1, r2, cpvrotate(n, cpv(
|
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
|
}
|