16
|
1
|
|
2 // written in the D programming language
|
|
3
|
|
4 module samples.Joints;
|
|
5
|
|
6 import chipmunkd.chipmunk;
|
|
7
|
|
8 import samples.ChipmunkDemo;
|
|
9
|
|
10 import std.math;
|
|
11
|
|
12 static cpSpace *space;
|
|
13
|
|
14 enum M_PI = PI;
|
|
15 enum M_PI_2 = PI*0.5f;
|
|
16
|
|
17 static cpBody *
|
|
18 addBall(cpVect pos, cpVect boxOffset)
|
|
19 {
|
|
20 cpFloat radius = 15.0f;
|
|
21 cpFloat mass = 1.0f;
|
|
22 cpBody *_body = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForCircle(mass, 0.0f, radius, cpvzero)));
|
|
23 _body.p = cpvadd(pos, boxOffset);
|
|
24
|
|
25 cpShape *shape = cpSpaceAddShape(space, cpCircleShapeNew(_body, radius, cpvzero));
|
|
26 shape.e = 0.0f; shape.u = 0.7f;
|
|
27
|
|
28 return _body;
|
|
29 }
|
|
30
|
|
31 static cpBody *
|
|
32 addLever(cpVect pos, cpVect boxOffset)
|
|
33 {
|
|
34 cpFloat mass = 1.0f;
|
|
35 cpVect a = cpv(0, 15);
|
|
36 cpVect b = cpv(0, -15);
|
|
37
|
|
38 cpBody *_body = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForSegment(mass, a, b)));
|
|
39 _body.p = cpvadd(pos, cpvadd(boxOffset, cpv(0, -15)));
|
|
40
|
|
41 cpShape *shape = cpSpaceAddShape(space, cpSegmentShapeNew(_body, a, b, 5.0f));
|
|
42 shape.e = 0.0f; shape.u = 0.7f;
|
|
43
|
|
44 return _body;
|
|
45 }
|
|
46
|
|
47 static cpBody *
|
|
48 addBar(cpVect pos, cpVect boxOffset)
|
|
49 {
|
|
50 cpFloat mass = 2.0f;
|
|
51 cpVect a = cpv(0, 30);
|
|
52 cpVect b = cpv(0, -30);
|
|
53
|
|
54 cpBody *_body = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForSegment(mass, a, b)));
|
|
55 _body.p = cpvadd(pos, boxOffset);
|
|
56
|
|
57 cpShape *shape = cpSpaceAddShape(space, cpSegmentShapeNew(_body, a, b, 5.0f));
|
|
58 shape.e = 0.0f; shape.u = 0.7f;
|
|
59
|
|
60 return _body;
|
|
61 }
|
|
62
|
|
63 static cpBody *
|
|
64 addWheel(cpVect pos, cpVect boxOffset)
|
|
65 {
|
|
66 cpFloat radius = 15.0f;
|
|
67 cpFloat mass = 1.0f;
|
|
68 cpBody *_body = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForCircle(mass, 0.0f, radius, cpvzero)));
|
|
69 _body.p = cpvadd(pos, boxOffset);
|
|
70
|
|
71 cpShape *shape = cpSpaceAddShape(space, cpCircleShapeNew(_body, radius, cpvzero));
|
|
72 shape.e = 0.0f; shape.u = 0.7f;
|
|
73 shape.group = 1; // use a group to keep the car parts from colliding
|
|
74
|
|
75 return _body;
|
|
76 }
|
|
77
|
|
78 static cpBody *
|
|
79 addChassis(cpVect pos, cpVect boxOffset)
|
|
80 {
|
|
81 int num = 4;
|
|
82 cpVect verts[] = [
|
|
83 cpv(-40,-15),
|
|
84 cpv(-40, 15),
|
|
85 cpv( 40, 15),
|
|
86 cpv( 40,-15),
|
|
87 ];
|
|
88
|
|
89
|
|
90 cpFloat mass = 5.0f;
|
|
91 cpBody *_body = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForPoly(mass, num, verts.ptr, cpvzero)));
|
|
92 _body.p = cpvadd(pos, boxOffset);
|
|
93
|
|
94 cpShape *shape = cpSpaceAddShape(space, cpPolyShapeNew(_body, num, verts.ptr, cpvzero));
|
|
95 shape.e = 0.0f; shape.u = 0.7f;
|
|
96 shape.group = 1; // use a group to keep the car parts from colliding
|
|
97
|
|
98 return _body;
|
|
99 }
|
|
100
|
|
101 static cpSpace *
|
|
102 init()
|
|
103 {
|
|
104 space = cpSpaceNew();
|
|
105 space.iterations = 10;
|
|
106 space.gravity = cpv(0, -100);
|
|
107 space.sleepTimeThreshold = 0.5f;
|
|
108
|
|
109 cpBody *staticBody = &space.staticBody;
|
|
110 cpShape *shape;
|
|
111
|
|
112 shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,240), cpv(320,240), 0.0f));
|
|
113 shape.e = 1.0f; shape.u = 1.0f;
|
|
114 shape.layers = NOT_GRABABLE_MASK;
|
|
115
|
|
116 shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,120), cpv(320,120), 0.0f));
|
|
117 shape.e = 1.0f; shape.u = 1.0f;
|
|
118 shape.layers = NOT_GRABABLE_MASK;
|
|
119
|
|
120 shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,0), cpv(320,0), 0.0f));
|
|
121 shape.e = 1.0f; shape.u = 1.0f;
|
|
122 shape.layers = NOT_GRABABLE_MASK;
|
|
123
|
|
124 shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,-120), cpv(320,-120), 0.0f));
|
|
125 shape.e = 1.0f; shape.u = 1.0f;
|
|
126 shape.layers = NOT_GRABABLE_MASK;
|
|
127
|
|
128 shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,-240), cpv(320,-240), 0.0f));
|
|
129 shape.e = 1.0f; shape.u = 1.0f;
|
|
130 shape.layers = NOT_GRABABLE_MASK;
|
|
131
|
|
132
|
|
133 shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,-240), cpv(-320,240), 0.0f));
|
|
134 shape.e = 1.0f; shape.u = 1.0f;
|
|
135 shape.layers = NOT_GRABABLE_MASK;
|
|
136
|
|
137 shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-160,-240), cpv(-160,240), 0.0f));
|
|
138 shape.e = 1.0f; shape.u = 1.0f;
|
|
139 shape.layers = NOT_GRABABLE_MASK;
|
|
140
|
|
141 shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(0,-240), cpv(0,240), 0.0f));
|
|
142 shape.e = 1.0f; shape.u = 1.0f;
|
|
143 shape.layers = NOT_GRABABLE_MASK;
|
|
144
|
|
145 shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(160,-240), cpv(160,240), 0.0f));
|
|
146 shape.e = 1.0f; shape.u = 1.0f;
|
|
147 shape.layers = NOT_GRABABLE_MASK;
|
|
148
|
|
149 shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(320,-240), cpv(320,240), 0.0f));
|
|
150 shape.e = 1.0f; shape.u = 1.0f;
|
|
151 shape.layers = NOT_GRABABLE_MASK;
|
|
152
|
|
153 cpVect boxOffset;
|
|
154 cpBody *body1;
|
|
155 cpBody *body2;
|
|
156
|
|
157 cpVect posA = cpv( 50, 60);
|
|
158 cpVect posB = cpv(110, 60);
|
|
159
|
|
160 // Pin Joints - Link shapes with a solid bar or pin.
|
|
161 // Keeps the anchor points the same distance apart from when the joint was created.
|
|
162 boxOffset = cpv(-320, -240);
|
|
163 body1 = addBall(posA, boxOffset);
|
|
164 body2 = addBall(posB, boxOffset);
|
|
165 cpSpaceAddConstraint(space, cpPinJointNew(body1, body2, cpv(15,0), cpv(-15,0)));
|
|
166
|
|
167 // Slide Joints - Like pin joints but with a min/max distance.
|
|
168 // Can be used for a cheap approximation of a rope.
|
|
169 boxOffset = cpv(-160, -240);
|
|
170 body1 = addBall(posA, boxOffset);
|
|
171 body2 = addBall(posB, boxOffset);
|
|
172 cpSpaceAddConstraint(space, cpSlideJointNew(body1, body2, cpv(15,0), cpv(-15,0), 20.0f, 40.0f));
|
|
173
|
|
174 // Pivot Joints - Holds the two anchor points together. Like a swivel.
|
|
175 boxOffset = cpv(0, -240);
|
|
176 body1 = addBall(posA, boxOffset);
|
|
177 body2 = addBall(posB, boxOffset);
|
|
178 cpSpaceAddConstraint(space, cpPivotJointNew(body1, body2, cpvadd(boxOffset, cpv(80,60))));
|
|
179 // cpPivotJointNew() takes it's anchor parameter in world coordinates. The anchors are calculated from that
|
|
180 // cpPivotJointNew2() lets you specify the two anchor points explicitly
|
|
181
|
|
182 // Groove Joints - Like a pivot joint, but one of the anchors is a line segment that the pivot can slide in
|
|
183 boxOffset = cpv(160, -240);
|
|
184 body1 = addBall(posA, boxOffset);
|
|
185 body2 = addBall(posB, boxOffset);
|
|
186 cpSpaceAddConstraint(space, cpGrooveJointNew(body1, body2, cpv(30,30), cpv(30,-30), cpv(-30,0)));
|
|
187
|
|
188 // Damped Springs
|
|
189 boxOffset = cpv(-320, -120);
|
|
190 body1 = addBall(posA, boxOffset);
|
|
191 body2 = addBall(posB, boxOffset);
|
|
192 cpSpaceAddConstraint(space, cpDampedSpringNew(body1, body2, cpv(15,0), cpv(-15,0), 20.0f, 5.0f, 0.3f));
|
|
193
|
|
194 // Damped Rotary Springs
|
|
195 boxOffset = cpv(-160, -120);
|
|
196 body1 = addBar(posA, boxOffset);
|
|
197 body2 = addBar(posB, boxOffset);
|
|
198 // Add some pin joints to hold the circles in place.
|
|
199 cpSpaceAddConstraint(space, cpPivotJointNew(body1, staticBody, cpvadd(boxOffset, posA)));
|
|
200 cpSpaceAddConstraint(space, cpPivotJointNew(body2, staticBody, cpvadd(boxOffset, posB)));
|
|
201 cpSpaceAddConstraint(space, cpDampedRotarySpringNew(body1, body2, 0.0f, 3000.0f, 60.0f));
|
|
202
|
|
203 // Rotary Limit Joint
|
|
204 boxOffset = cpv(0, -120);
|
|
205 body1 = addLever(posA, boxOffset);
|
|
206 body2 = addLever(posB, boxOffset);
|
|
207 // Add some pin joints to hold the circles in place.
|
|
208 cpSpaceAddConstraint(space, cpPivotJointNew(body1, staticBody, cpvadd(boxOffset, posA)));
|
|
209 cpSpaceAddConstraint(space, cpPivotJointNew(body2, staticBody, cpvadd(boxOffset, posB)));
|
|
210 // Hold their rotation within 90 degrees of each other.
|
|
211 cpSpaceAddConstraint(space, cpRotaryLimitJointNew(body1, body2, -M_PI_2, M_PI_2));
|
|
212
|
|
213 // Ratchet Joint - A rotary ratchet, like a socket wrench
|
|
214 boxOffset = cpv(160, -120);
|
|
215 body1 = addLever(posA, boxOffset);
|
|
216 body2 = addLever(posB, boxOffset);
|
|
217 // Add some pin joints to hold the circles in place.
|
|
218 cpSpaceAddConstraint(space, cpPivotJointNew(body1, staticBody, cpvadd(boxOffset, posA)));
|
|
219 cpSpaceAddConstraint(space, cpPivotJointNew(body2, staticBody, cpvadd(boxOffset, posB)));
|
|
220 // Ratchet every 90 degrees
|
|
221 cpSpaceAddConstraint(space, cpRatchetJointNew(body1, body2, 0.0f, M_PI_2));
|
|
222
|
|
223 // Gear Joint - Maintain a specific angular velocity ratio
|
|
224 boxOffset = cpv(-320, 0);
|
|
225 body1 = addBar(posA, boxOffset);
|
|
226 body2 = addBar(posB, boxOffset);
|
|
227 // Add some pin joints to hold the circles in place.
|
|
228 cpSpaceAddConstraint(space, cpPivotJointNew(body1, staticBody, cpvadd(boxOffset, posA)));
|
|
229 cpSpaceAddConstraint(space, cpPivotJointNew(body2, staticBody, cpvadd(boxOffset, posB)));
|
|
230 // Force one to sping 2x as fast as the other
|
|
231 cpSpaceAddConstraint(space, cpGearJointNew(body1, body2, 0.0f, 2.0f));
|
|
232
|
|
233 // Simple Motor - Maintain a specific angular relative velocity
|
|
234 boxOffset = cpv(-160, 0);
|
|
235 body1 = addBar(posA, boxOffset);
|
|
236 body2 = addBar(posB, boxOffset);
|
|
237 // Add some pin joints to hold the circles in place.
|
|
238 cpSpaceAddConstraint(space, cpPivotJointNew(body1, staticBody, cpvadd(boxOffset, posA)));
|
|
239 cpSpaceAddConstraint(space, cpPivotJointNew(body2, staticBody, cpvadd(boxOffset, posB)));
|
|
240 // Make them spin at 1/2 revolution per second in relation to each other.
|
|
241 cpSpaceAddConstraint(space, cpSimpleMotorNew(body1, body2, M_PI));
|
|
242
|
|
243 // Make a car with some nice soft suspension
|
|
244 boxOffset = cpv(0, 0);
|
|
245 cpBody *wheel1 = addWheel(posA, boxOffset);
|
|
246 cpBody *wheel2 = addWheel(posB, boxOffset);
|
|
247 cpBody *chassis = addChassis(cpv(80, 100), boxOffset);
|
|
248
|
|
249 cpSpaceAddConstraint(space, cpGrooveJointNew(chassis, wheel1, cpv(-30, -10), cpv(-30, -40), cpvzero));
|
|
250 cpSpaceAddConstraint(space, cpGrooveJointNew(chassis, wheel2, cpv( 30, -10), cpv( 30, -40), cpvzero));
|
|
251
|
|
252 cpSpaceAddConstraint(space, cpDampedSpringNew(chassis, wheel1, cpv(-30, 0), cpvzero, 50.0f, 20.0f, 1.5f));
|
|
253 cpSpaceAddConstraint(space, cpDampedSpringNew(chassis, wheel2, cpv( 30, 0), cpvzero, 50.0f, 20.0f, 1.5f));
|
|
254
|
|
255 return space;
|
|
256 }
|
|
257
|
|
258 static void
|
|
259 update(int ticks)
|
|
260 {
|
|
261 cpSpaceStep(space, 1.0f/60.0f);
|
|
262 }
|
|
263
|
|
264 static void
|
|
265 destroy()
|
|
266 {
|
|
267 cpSpaceFreeChildren(space);
|
|
268 cpSpaceFree(space);
|
|
269 }
|
|
270
|
|
271 chipmunkDemo Joints = {
|
|
272 "Joints and Constraints",
|
|
273 null,
|
|
274 &init,
|
|
275 &update,
|
|
276 &destroy,
|
|
277 };
|