chipmunk 4.1.0-x86-mswin32

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,122 @@
1
+ /* Copyright (c) 2007 Scott Lembcke
2
+ *
3
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ * of this software and associated documentation files (the "Software"), to deal
5
+ * in the Software without restriction, including without limitation the rights
6
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ * copies of the Software, and to permit persons to whom the Software is
8
+ * furnished to do so, subject to the following conditions:
9
+ *
10
+ * The above copyright notice and this permission notice shall be included in
11
+ * all copies or substantial portions of the Software.
12
+ *
13
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ * SOFTWARE.
20
+ */
21
+
22
+ // TODO: Comment me!
23
+
24
+ extern cpFloat cp_joint_bias_coef;
25
+
26
+ typedef enum cpJointType {
27
+ CP_PIN_JOINT,
28
+ CP_PIVOT_JOINT,
29
+ CP_SLIDE_JOINT,
30
+ CP_GROOVE_JOINT,
31
+ CP_CUSTOM_JOINT, // For user definable joint types.
32
+ } cpJointType;
33
+
34
+ struct cpJoint;
35
+ struct cpJointClass;
36
+
37
+ typedef struct cpJointClass {
38
+ cpJointType type;
39
+
40
+ void (*preStep)(struct cpJoint *joint, cpFloat dt_inv);
41
+ void (*applyImpulse)(struct cpJoint *joint);
42
+ } cpJointClass;
43
+
44
+ typedef struct cpJoint {
45
+ const cpJointClass *klass;
46
+
47
+ cpBody *a, *b;
48
+ } cpJoint;
49
+
50
+ void cpJointDestroy(cpJoint *joint);
51
+ void cpJointFree(cpJoint *joint);
52
+
53
+
54
+ typedef struct cpPinJoint {
55
+ cpJoint joint;
56
+ cpVect anchr1, anchr2;
57
+ cpFloat dist;
58
+
59
+ cpVect r1, r2;
60
+ cpVect n;
61
+ cpFloat nMass;
62
+
63
+ cpFloat jnAcc, jBias;
64
+ cpFloat bias;
65
+ } cpPinJoint;
66
+
67
+ cpPinJoint *cpPinJointAlloc(void);
68
+ cpPinJoint *cpPinJointInit(cpPinJoint *joint, cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2);
69
+ cpJoint *cpPinJointNew(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2);
70
+
71
+
72
+ typedef struct cpSlideJoint {
73
+ cpJoint joint;
74
+ cpVect anchr1, anchr2;
75
+ cpFloat min, max;
76
+
77
+ cpVect r1, r2;
78
+ cpVect n;
79
+ cpFloat nMass;
80
+
81
+ cpFloat jnAcc, jBias;
82
+ cpFloat bias;
83
+ } cpSlideJoint;
84
+
85
+ cpSlideJoint *cpSlideJointAlloc(void);
86
+ cpSlideJoint *cpSlideJointInit(cpSlideJoint *joint, cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat min, cpFloat max);
87
+ cpJoint *cpSlideJointNew(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat min, cpFloat max);
88
+
89
+
90
+ typedef struct cpPivotJoint {
91
+ cpJoint joint;
92
+ cpVect anchr1, anchr2;
93
+
94
+ cpVect r1, r2;
95
+ cpVect k1, k2;
96
+
97
+ cpVect jAcc, jBias;
98
+ cpVect bias;
99
+ } cpPivotJoint;
100
+
101
+ cpPivotJoint *cpPivotJointAlloc(void);
102
+ cpPivotJoint *cpPivotJointInit(cpPivotJoint *joint, cpBody *a, cpBody *b, cpVect pivot);
103
+ cpJoint *cpPivotJointNew(cpBody *a, cpBody *b, cpVect pivot);
104
+
105
+
106
+ typedef struct cpGrooveJoint {
107
+ cpJoint joint;
108
+ cpVect grv_n, grv_a, grv_b;
109
+ cpVect anchr2;
110
+
111
+ cpVect grv_tn;
112
+ cpFloat clamp;
113
+ cpVect r1, r2;
114
+ cpVect k1, k2;
115
+
116
+ cpVect jAcc, jBias;
117
+ cpVect bias;
118
+ } cpGrooveJoint;
119
+
120
+ cpGrooveJoint *cpGrooveJointAlloc(void);
121
+ cpGrooveJoint *cpGrooveJointInit(cpGrooveJoint *joint, cpBody *a, cpBody *b, cpVect groove_a, cpVect groove_b, cpVect anchr2);
122
+ cpJoint *cpGrooveJointNew(cpBody *a, cpBody *b, cpVect groove_a, cpVect groove_b, cpVect anchr2);
@@ -0,0 +1,139 @@
1
+ /* Copyright (c) 2007 Scott Lembcke
2
+ *
3
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ * of this software and associated documentation files (the "Software"), to deal
5
+ * in the Software without restriction, including without limitation the rights
6
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ * copies of the Software, and to permit persons to whom the Software is
8
+ * furnished to do so, subject to the following conditions:
9
+ *
10
+ * The above copyright notice and this permission notice shall be included in
11
+ * all copies or substantial portions of the Software.
12
+ *
13
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ * SOFTWARE.
20
+ */
21
+
22
+ #include <stdlib.h>
23
+ #include <stdio.h>
24
+ #include <math.h>
25
+
26
+ #include "chipmunk.h"
27
+
28
+ cpPolyShape *
29
+ cpPolyShapeAlloc(void)
30
+ {
31
+ return (cpPolyShape *)calloc(1, sizeof(cpPolyShape));
32
+ }
33
+
34
+ static void
35
+ cpPolyShapeTransformVerts(cpPolyShape *poly, cpVect p, cpVect rot)
36
+ {
37
+ cpVect *src = poly->verts;
38
+ cpVect *dst = poly->tVerts;
39
+
40
+ for(int i=0; i<poly->numVerts; i++)
41
+ dst[i] = cpvadd(p, cpvrotate(src[i], rot));
42
+ }
43
+
44
+ static void
45
+ cpPolyShapeTransformAxes(cpPolyShape *poly, cpVect p, cpVect rot)
46
+ {
47
+ cpPolyShapeAxis *src = poly->axes;
48
+ cpPolyShapeAxis *dst = poly->tAxes;
49
+
50
+ for(int i=0; i<poly->numVerts; i++){
51
+ cpVect n = cpvrotate(src[i].n, rot);
52
+ dst[i].n = n;
53
+ dst[i].d = cpvdot(p, n) + src[i].d;
54
+ }
55
+ }
56
+
57
+ static cpBB
58
+ cpPolyShapeCacheData(cpShape *shape, cpVect p, cpVect rot)
59
+ {
60
+ cpPolyShape *poly = (cpPolyShape *)shape;
61
+
62
+ cpFloat l, b, r, t;
63
+
64
+ cpPolyShapeTransformAxes(poly, p, rot);
65
+ cpPolyShapeTransformVerts(poly, p, rot);
66
+
67
+ cpVect *verts = poly->tVerts;
68
+ l = r = verts[0].x;
69
+ b = t = verts[0].y;
70
+
71
+ // TODO do as part of cpPolyShapeTransformVerts?
72
+ for(int i=1; i<poly->numVerts; i++){
73
+ cpVect v = verts[i];
74
+
75
+ l = cpfmin(l, v.x);
76
+ r = cpfmax(r, v.x);
77
+
78
+ b = cpfmin(b, v.y);
79
+ t = cpfmax(t, v.y);
80
+ }
81
+
82
+ return cpBBNew(l, b, r, t);
83
+ }
84
+
85
+ static void
86
+ cpPolyShapeDestroy(cpShape *shape)
87
+ {
88
+ cpPolyShape *poly = (cpPolyShape *)shape;
89
+
90
+ free(poly->verts);
91
+ free(poly->tVerts);
92
+
93
+ free(poly->axes);
94
+ free(poly->tAxes);
95
+ }
96
+
97
+ static int
98
+ cpPolyShapePointQuery(cpShape *shape, cpVect p){
99
+ // TODO Check against BB first?
100
+ return cpPolyShapeContainsVert((cpPolyShape *)shape, p);
101
+ }
102
+
103
+ static const cpShapeClass polyClass = {
104
+ CP_POLY_SHAPE,
105
+ cpPolyShapeCacheData,
106
+ cpPolyShapeDestroy,
107
+ cpPolyShapePointQuery,
108
+ };
109
+
110
+ cpPolyShape *
111
+ cpPolyShapeInit(cpPolyShape *poly, cpBody *body, int numVerts, cpVect *verts, cpVect offset)
112
+ {
113
+ poly->numVerts = numVerts;
114
+
115
+ poly->verts = (cpVect *)calloc(numVerts, sizeof(cpVect));
116
+ poly->tVerts = (cpVect *)calloc(numVerts, sizeof(cpVect));
117
+ poly->axes = (cpPolyShapeAxis *)calloc(numVerts, sizeof(cpPolyShapeAxis));
118
+ poly->tAxes = (cpPolyShapeAxis *)calloc(numVerts, sizeof(cpPolyShapeAxis));
119
+
120
+ for(int i=0; i<numVerts; i++){
121
+ cpVect a = cpvadd(offset, verts[i]);
122
+ cpVect b = cpvadd(offset, verts[(i+1)%numVerts]);
123
+ cpVect n = cpvnormalize(cpvperp(cpvsub(b, a)));
124
+
125
+ poly->verts[i] = a;
126
+ poly->axes[i].n = n;
127
+ poly->axes[i].d = cpvdot(n, a);
128
+ }
129
+
130
+ cpShapeInit((cpShape *)poly, &polyClass, body);
131
+
132
+ return poly;
133
+ }
134
+
135
+ cpShape *
136
+ cpPolyShapeNew(cpBody *body, int numVerts, cpVect *verts, cpVect offset)
137
+ {
138
+ return (cpShape *)cpPolyShapeInit(cpPolyShapeAlloc(), body, numVerts, verts, offset);
139
+ }
@@ -0,0 +1,92 @@
1
+ /* Copyright (c) 2007 Scott Lembcke
2
+ *
3
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ * of this software and associated documentation files (the "Software"), to deal
5
+ * in the Software without restriction, including without limitation the rights
6
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ * copies of the Software, and to permit persons to whom the Software is
8
+ * furnished to do so, subject to the following conditions:
9
+ *
10
+ * The above copyright notice and this permission notice shall be included in
11
+ * all copies or substantial portions of the Software.
12
+ *
13
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ * SOFTWARE.
20
+ */
21
+
22
+ // Axis structure used by cpPolyShape.
23
+ typedef struct cpPolyShapeAxis{
24
+ // normal
25
+ cpVect n;
26
+ // distance from origin
27
+ cpFloat d;
28
+ } cpPolyShapeAxis;
29
+
30
+ // Convex polygon shape structure.
31
+ typedef struct cpPolyShape{
32
+ cpShape shape;
33
+
34
+ // Vertex and axis lists.
35
+ int numVerts;
36
+ cpVect *verts;
37
+ cpPolyShapeAxis *axes;
38
+
39
+ // Transformed vertex and axis lists.
40
+ cpVect *tVerts;
41
+ cpPolyShapeAxis *tAxes;
42
+ } cpPolyShape;
43
+
44
+ // Basic allocation functions.
45
+ cpPolyShape *cpPolyShapeAlloc(void);
46
+ cpPolyShape *cpPolyShapeInit(cpPolyShape *poly, cpBody *body, int numVerts, cpVect *verts, cpVect offset);
47
+ cpShape *cpPolyShapeNew(cpBody *body, int numVerts, cpVect *verts, cpVect offset);
48
+
49
+ // Returns the minimum distance of the polygon to the axis.
50
+ static inline cpFloat
51
+ cpPolyShapeValueOnAxis(const cpPolyShape *poly, const cpVect n, const cpFloat d)
52
+ {
53
+ cpVect *verts = poly->tVerts;
54
+ cpFloat min = cpvdot(n, verts[0]);
55
+
56
+ int i;
57
+ for(i=1; i<poly->numVerts; i++)
58
+ min = cpfmin(min, cpvdot(n, verts[i]));
59
+
60
+ return min - d;
61
+ }
62
+
63
+ // Returns true if the polygon contains the vertex.
64
+ static inline int
65
+ cpPolyShapeContainsVert(cpPolyShape *poly, cpVect v)
66
+ {
67
+ cpPolyShapeAxis *axes = poly->tAxes;
68
+
69
+ int i;
70
+ for(i=0; i<poly->numVerts; i++){
71
+ cpFloat dist = cpvdot(axes[i].n, v) - axes[i].d;
72
+ if(dist > 0.0) return 0;
73
+ }
74
+
75
+ return 1;
76
+ }
77
+
78
+ // Same as cpPolyShapeContainsVert() but ignores faces pointing away from the normal.
79
+ static inline int
80
+ cpPolyShapeContainsVertPartial(cpPolyShape *poly, cpVect v, cpVect n)
81
+ {
82
+ cpPolyShapeAxis *axes = poly->tAxes;
83
+
84
+ int i;
85
+ for(i=0; i<poly->numVerts; i++){
86
+ if(cpvdot(axes[i].n, n) < 0.0f) continue;
87
+ cpFloat dist = cpvdot(axes[i].n, v) - axes[i].d;
88
+ if(dist > 0.0) return 0;
89
+ }
90
+
91
+ return 1;
92
+ }
@@ -0,0 +1,244 @@
1
+ /* Copyright (c) 2007 Scott Lembcke
2
+ *
3
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ * of this software and associated documentation files (the "Software"), to deal
5
+ * in the Software without restriction, including without limitation the rights
6
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ * copies of the Software, and to permit persons to whom the Software is
8
+ * furnished to do so, subject to the following conditions:
9
+ *
10
+ * The above copyright notice and this permission notice shall be included in
11
+ * all copies or substantial portions of the Software.
12
+ *
13
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ * SOFTWARE.
20
+ */
21
+
22
+ #include <stdlib.h>
23
+ #include <assert.h>
24
+ #include <stdio.h>
25
+
26
+ #include "chipmunk.h"
27
+ #include "math.h"
28
+
29
+ unsigned int SHAPE_ID_COUNTER = 0;
30
+
31
+ void
32
+ cpResetShapeIdCounter(void)
33
+ {
34
+ SHAPE_ID_COUNTER = 0;
35
+ }
36
+
37
+
38
+ cpShape*
39
+ cpShapeInit(cpShape *shape, const cpShapeClass *klass, cpBody *body)
40
+ {
41
+ shape->klass = klass;
42
+
43
+ shape->id = SHAPE_ID_COUNTER;
44
+ SHAPE_ID_COUNTER++;
45
+
46
+ assert(body != NULL);
47
+ shape->body = body;
48
+
49
+ shape->e = 0.0f;
50
+ shape->u = 0.0f;
51
+ shape->surface_v = cpvzero;
52
+
53
+ shape->collision_type = 0;
54
+ shape->group = 0;
55
+ shape->layers = 0xFFFF;
56
+
57
+ shape->data = NULL;
58
+
59
+ cpShapeCacheBB(shape);
60
+
61
+ return shape;
62
+ }
63
+
64
+ void
65
+ cpShapeDestroy(cpShape *shape)
66
+ {
67
+ if(shape->klass->destroy) shape->klass->destroy(shape);
68
+ }
69
+
70
+ void
71
+ cpShapeFree(cpShape *shape)
72
+ {
73
+ if(shape) cpShapeDestroy(shape);
74
+ free(shape);
75
+ }
76
+
77
+ cpBB
78
+ cpShapeCacheBB(cpShape *shape)
79
+ {
80
+ cpBody *body = shape->body;
81
+
82
+ shape->bb = shape->klass->cacheData(shape, body->p, body->rot);
83
+ return shape->bb;
84
+ }
85
+
86
+ int
87
+ cpShapePointQuery(cpShape *shape, cpVect p){
88
+ return shape->klass->pointQuery(shape, p);
89
+ }
90
+
91
+
92
+
93
+ cpCircleShape *
94
+ cpCircleShapeAlloc(void)
95
+ {
96
+ return (cpCircleShape *)calloc(1, sizeof(cpCircleShape));
97
+ }
98
+
99
+ static inline cpBB
100
+ bbFromCircle(const cpVect c, const cpFloat r)
101
+ {
102
+ return cpBBNew(c.x-r, c.y-r, c.x+r, c.y+r);
103
+ }
104
+
105
+ static cpBB
106
+ cpCircleShapeCacheData(cpShape *shape, cpVect p, cpVect rot)
107
+ {
108
+ cpCircleShape *circle = (cpCircleShape *)shape;
109
+
110
+ circle->tc = cpvadd(p, cpvrotate(circle->c, rot));
111
+ return bbFromCircle(circle->tc, circle->r);
112
+ }
113
+
114
+ static int
115
+ cpCircleShapePointQuery(cpShape *shape, cpVect p){
116
+ cpCircleShape *circle = (cpCircleShape *)shape;
117
+
118
+ cpFloat distSQ = cpvlengthsq(cpvsub(circle->tc, p));
119
+ return distSQ <= (circle->r*circle->r);
120
+ }
121
+
122
+ static const cpShapeClass circleClass = {
123
+ CP_CIRCLE_SHAPE,
124
+ cpCircleShapeCacheData,
125
+ NULL,
126
+ cpCircleShapePointQuery,
127
+ };
128
+
129
+ cpCircleShape *
130
+ cpCircleShapeInit(cpCircleShape *circle, cpBody *body, cpFloat radius, cpVect offset)
131
+ {
132
+ circle->c = offset;
133
+ circle->r = radius;
134
+
135
+ cpShapeInit((cpShape *)circle, &circleClass, body);
136
+
137
+ return circle;
138
+ }
139
+
140
+ cpShape *
141
+ cpCircleShapeNew(cpBody *body, cpFloat radius, cpVect offset)
142
+ {
143
+ return (cpShape *)cpCircleShapeInit(cpCircleShapeAlloc(), body, radius, offset);
144
+ }
145
+
146
+ cpSegmentShape *
147
+ cpSegmentShapeAlloc(void)
148
+ {
149
+ return (cpSegmentShape *)calloc(1, sizeof(cpSegmentShape));
150
+ }
151
+
152
+ static cpBB
153
+ cpSegmentShapeCacheData(cpShape *shape, cpVect p, cpVect rot)
154
+ {
155
+ cpSegmentShape *seg = (cpSegmentShape *)shape;
156
+
157
+ seg->ta = cpvadd(p, cpvrotate(seg->a, rot));
158
+ seg->tb = cpvadd(p, cpvrotate(seg->b, rot));
159
+ seg->tn = cpvrotate(seg->n, rot);
160
+
161
+ cpFloat l,r,s,t;
162
+
163
+ if(seg->ta.x < seg->tb.x){
164
+ l = seg->ta.x;
165
+ r = seg->tb.x;
166
+ } else {
167
+ l = seg->tb.x;
168
+ r = seg->ta.x;
169
+ }
170
+
171
+ if(seg->ta.y < seg->tb.y){
172
+ s = seg->ta.y;
173
+ t = seg->tb.y;
174
+ } else {
175
+ s = seg->tb.y;
176
+ t = seg->ta.y;
177
+ }
178
+
179
+ cpFloat rad = seg->r;
180
+ return cpBBNew(l - rad, s - rad, r + rad, t + rad);
181
+ }
182
+
183
+ static int
184
+ cpSegmentShapePointQuery(cpShape *shape, cpVect p){
185
+ cpSegmentShape *seg = (cpSegmentShape *)shape;
186
+
187
+ // Calculate normal distance from segment.
188
+ cpFloat dn = cpvdot(seg->tn, p) - cpvdot(seg->ta, seg->tn);
189
+ cpFloat dist = fabs(dn) - seg->r;
190
+ if(dist > 0.0f) return 0;
191
+
192
+ // Calculate tangential distance along segment.
193
+ cpFloat dt = -cpvcross(seg->tn, p);
194
+ cpFloat dtMin = -cpvcross(seg->tn, seg->ta);
195
+ cpFloat dtMax = -cpvcross(seg->tn, seg->tb);
196
+
197
+ // Decision tree to decide which feature of the segment to collide with.
198
+ if(dt <= dtMin){
199
+ if(dt < (dtMin - seg->r)){
200
+ return 0;
201
+ } else {
202
+ return cpvlengthsq(cpvsub(seg->ta, p)) < (seg->r*seg->r);
203
+ }
204
+ } else {
205
+ if(dt < dtMax){
206
+ return 1;
207
+ } else {
208
+ if(dt < (dtMax + seg->r)) {
209
+ return cpvlengthsq(cpvsub(seg->tb, p)) < (seg->r*seg->r);
210
+ } else {
211
+ return 0;
212
+ }
213
+ }
214
+ }
215
+
216
+ return 1;
217
+ }
218
+
219
+ static const cpShapeClass segmentClass = {
220
+ CP_SEGMENT_SHAPE,
221
+ cpSegmentShapeCacheData,
222
+ NULL,
223
+ cpSegmentShapePointQuery,
224
+ };
225
+
226
+ cpSegmentShape *
227
+ cpSegmentShapeInit(cpSegmentShape *seg, cpBody *body, cpVect a, cpVect b, cpFloat r)
228
+ {
229
+ seg->a = a;
230
+ seg->b = b;
231
+ seg->n = cpvperp(cpvnormalize(cpvsub(b, a)));
232
+
233
+ seg->r = r;
234
+
235
+ cpShapeInit((cpShape *)seg, &segmentClass, body);
236
+
237
+ return seg;
238
+ }
239
+
240
+ cpShape*
241
+ cpSegmentShapeNew(cpBody *body, cpVect a, cpVect b, cpFloat r)
242
+ {
243
+ return (cpShape *)cpSegmentShapeInit(cpSegmentShapeAlloc(), body, a, b, r);
244
+ }