1 /*
2  * Copyright (c) 2007-2013 Scott Lembcke and Howling Moon Software
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to deal
6  * in the Software without restriction, including without limitation the rights
7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20  * SOFTWARE.
21  */
22 module demo.Bench;
23 
24 import std.math;
25 
26 import demo.dchip;
27 import demo.ChipmunkDemo;
28 
29 alias BENCH_SPACE_NEW = cpSpaceNew;
30 alias BENCH_SPACE_FREE = cpSpaceFree;
31 alias BENCH_SPACE_STEP = cpSpaceStep;
32 
33 const cpFloat bevel = 0.0;
34 
35 immutable cpVect[] simple_terrain_verts = [
36     { 350.00, 425.07 }, { 336.00, 436.55 }, { 272.00, 435.39 }, { 258.00, 427.63 }, { 225.28, 420.00 }, { 202.82, 396.00 },
37     { 191.81, 388.00 }, { 189.00, 381.89 }, { 173.00, 380.39 }, { 162.59, 368.00 }, { 150.47, 319.00 }, { 128.00, 311.55 },
38     { 119.14, 286.00 }, { 126.84, 263.00 }, { 120.56, 227.00 }, { 141.14, 178.00 }, { 137.52, 162.00 }, { 146.51, 142.00 },
39     { 156.23, 136.00 }, { 158.00, 118.27 }, { 170.00, 100.77 }, { 208.43, 84.00 }, { 224.00, 69.65 }, { 249.30, 68.00 },
40     { 257.00, 54.77 }, { 363.00, 45.94 }, { 374.15, 54.00 }, { 386.00, 69.60 }, { 413.00, 70.73 }, { 456.00, 84.89 },
41     { 468.09, 99.00 }, { 467.09, 123.00 }, { 464.92, 135.00 }, { 469.00, 141.03 }, { 497.00, 148.67 }, { 513.85, 180.00 },
42     { 509.56, 223.00 }, { 523.51, 247.00 }, { 523.00, 277.00 }, { 497.79, 311.00 }, { 478.67, 348.00 }, { 467.90, 360.00 },
43     { 456.76, 382.00 }, { 432.95, 389.00 }, { 417.00, 411.32 }, { 373.00, 433.19 }, { 361.00, 430.02 }, { 350.00, 425.07 },
44 ];
45 
46 immutable simple_terrain_count = simple_terrain_verts.length;
47 
48 //cpBody bodies[1000] = {};
49 //cpCircleShape circles[1000] = {};
50 
51 void add_circle(cpSpace* space, int index, cpFloat radius)
52 {
53     cpFloat mass = radius * radius / 25.0f;
54     cpBody* body_ = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForCircle(mass, 0.0f, radius, cpvzero)));
55 
56     //	cpBody *body_ = cpSpaceAddBody(space, cpBodyInit(&bodies[i], mass, cpMomentForCircle(mass, 0.0f, radius, cpvzero)));
57     body_.p = cpvmult(frand_unit_circle(), 180.0f);
58 
59     cpShape* shape = cpSpaceAddShape(space, cpCircleShapeNew(body_, radius, cpvzero));
60 
61     //	cpShape *shape = cpSpaceAddShape(space, cpCircleShapeInit(&circles[i], body_, radius, cpvzero));
62     shape.e = 0.0f;
63     shape.u = 0.9f;
64 }
65 
66 void add_box(cpSpace* space, int index, cpFloat size)
67 {
68     cpFloat mass = size * size / 100.0f;
69     cpBody* body_ = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForBox(mass, size, size)));
70 
71     //	cpBody *body_ = cpSpaceAddBody(space, cpBodyInit(&bodies[i], mass, cpMomentForBox(mass, size, size)));
72     body_.p = cpvmult(frand_unit_circle(), 180.0f);
73 
74     cpShape* shape = cpSpaceAddShape(space, cpBoxShapeNew(body_, size - bevel * 2, size - bevel * 2));
75     cpPolyShapeSetRadius(shape, bevel);
76     shape.e = 0.0f;
77     shape.u = 0.9f;
78 }
79 
80 void add_hexagon(cpSpace* space, int index, cpFloat radius)
81 {
82     cpVect hexagon[6] = {};
83 
84     for (int i = 0; i < 6; i++)
85     {
86         cpFloat angle = -M_PI * 2.0f * i / 6.0f;
87         hexagon[i] = cpvmult(cpv(cos(angle), sin(angle)), radius - bevel);
88     }
89 
90     cpFloat mass = radius * radius;
91     cpBody* body_ = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForPoly(mass, 6, hexagon.ptr, cpvzero)));
92     body_.p = cpvmult(frand_unit_circle(), 180.0f);
93 
94     cpShape* shape = cpSpaceAddShape(space, cpPolyShapeNew2(body_, 6, hexagon.ptr, cpvzero, bevel));
95     shape.e = 0.0f;
96     shape.u = 0.9f;
97 }
98 
99 cpSpace* SetupSpace_simpleTerrain()
100 {
101     cpSpace* space = BENCH_SPACE_NEW();
102     space.iterations    = 10;
103     space.gravity       = cpv(0, -100);
104     space.collisionSlop = 0.5f;
105 
106     cpVect offset = cpv(-320, -240);
107 
108     for (int i = 0; i < (simple_terrain_count - 1); i++)
109     {
110         cpVect a = simple_terrain_verts[i], b = simple_terrain_verts[i + 1];
111         cpSpaceAddShape(space, cpSegmentShapeNew(space.staticBody, cpvadd(a, offset), cpvadd(b, offset), 0.0f));
112     }
113 
114     return space;
115 }
116 
117 // SimpleTerrain constant sized objects
118 cpSpace* init_SimpleTerrainCircles_1000()
119 {
120     cpSpace* space;
121     space = SetupSpace_simpleTerrain();
122 
123     for (int i = 0; i < 1000; i++)
124         add_circle(space, i, 5.0f);
125 
126     return space;
127 }
128 
129 cpSpace* init_SimpleTerrainCircles_500()
130 {
131     cpSpace* space = SetupSpace_simpleTerrain();
132 
133     for (int i = 0; i < 500; i++)
134         add_circle(space, i, 5.0f);
135 
136     return space;
137 }
138 
139 cpSpace* init_SimpleTerrainCircles_100()
140 {
141     cpSpace* space = SetupSpace_simpleTerrain();
142 
143     for (int i = 0; i < 100; i++)
144         add_circle(space, i, 5.0f);
145 
146     return space;
147 }
148 
149 cpSpace* init_SimpleTerrainBoxes_1000()
150 {
151     cpSpace* space = SetupSpace_simpleTerrain();
152 
153     for (int i = 0; i < 1000; i++)
154         add_box(space, i, 10.0f);
155 
156     return space;
157 }
158 
159 cpSpace* init_SimpleTerrainBoxes_500()
160 {
161     cpSpace* space = SetupSpace_simpleTerrain();
162 
163     for (int i = 0; i < 500; i++)
164         add_box(space, i, 10.0f);
165 
166     return space;
167 }
168 
169 cpSpace* init_SimpleTerrainBoxes_100()
170 {
171     cpSpace* space = SetupSpace_simpleTerrain();
172 
173     for (int i = 0; i < 100; i++)
174         add_box(space, i, 10.0f);
175 
176     return space;
177 }
178 
179 cpSpace* init_SimpleTerrainHexagons_1000()
180 {
181     cpSpace* space = SetupSpace_simpleTerrain();
182 
183     for (int i = 0; i < 1000; i++)
184         add_hexagon(space, i, 5.0f);
185 
186     return space;
187 }
188 
189 cpSpace* init_SimpleTerrainHexagons_500()
190 {
191     cpSpace* space = SetupSpace_simpleTerrain();
192 
193     for (int i = 0; i < 500; i++)
194         add_hexagon(space, i, 5.0f);
195 
196     return space;
197 }
198 
199 cpSpace* init_SimpleTerrainHexagons_100()
200 {
201     cpSpace* space = SetupSpace_simpleTerrain();
202 
203     for (int i = 0; i < 100; i++)
204         add_hexagon(space, i, 5.0f);
205 
206     return space;
207 }
208 
209 // SimpleTerrain variable sized objects
210 cpFloat rand_size()
211 {
212     return cpfpow(1.5, cpflerp(-1.5, 3.5, frand()));
213 }
214 
215 cpSpace* init_SimpleTerrainVCircles_200()
216 {
217     cpSpace* space = SetupSpace_simpleTerrain();
218 
219     for (int i = 0; i < 200; i++)
220         add_circle(space, i, 5.0f * rand_size());
221 
222     return space;
223 }
224 
225 cpSpace* init_SimpleTerrainVBoxes_200()
226 {
227     cpSpace* space = SetupSpace_simpleTerrain();
228 
229     for (int i = 0; i < 200; i++)
230         add_box(space, i, 8.0f * rand_size());
231 
232     return space;
233 }
234 
235 cpSpace* init_SimpleTerrainVHexagons_200()
236 {
237     cpSpace* space = SetupSpace_simpleTerrain();
238 
239     for (int i = 0; i < 200; i++)
240         add_hexagon(space, i, 5.0f * rand_size());
241 
242     return space;
243 }
244 
245 // ComplexTerrain
246 immutable cpVect[] complex_terrain_verts = [
247     { 46.78, 479.00 }, { 35.00, 475.63 }, { 27.52, 469.00 }, { 23.52, 455.00 }, { 23.78, 441.00 }, { 28.41, 428.00 }, { 49.61, 394.00 }, { 59.00, 381.56 }, { 80.00, 366.03 }, { 81.46, 358.00 }, { 86.31, 350.00 }, { 77.74, 320.00 },
248     { 70.26, 278.00 }, { 67.51, 270.00 }, { 58.86, 260.00 }, { 57.19, 247.00 }, { 38.00, 235.60 }, { 25.76, 221.00 }, { 24.58, 209.00 }, { 27.63, 202.00 }, { 31.28, 198.00 }, { 40.00, 193.72 }, { 48.00, 193.73 }, { 55.00, 196.70 },
249     { 62.10, 204.00 }, { 71.00, 209.04 }, { 79.00, 206.55 }, { 88.00, 206.81 }, { 95.88, 211.00 }, { 103.00, 220.49 }, { 131.00, 220.51 }, { 137.00, 222.66 }, { 143.08, 228.00 }, { 146.22, 234.00 }, { 147.08, 241.00 }, { 145.45, 248.00 },
250     { 142.31, 253.00 }, { 132.00, 259.30 }, { 115.00, 259.70 }, { 109.28, 270.00 }, { 112.91, 296.00 }, { 119.69, 324.00 }, { 129.00, 336.26 }, { 141.00, 337.59 }, { 153.00, 331.57 }, { 175.00, 325.74 }, { 188.00, 325.19 }, { 235.00, 317.46 },
251     { 250.00, 317.19 }, { 255.00, 309.12 }, { 262.62, 302.00 }, { 262.21, 295.00 }, { 248.00, 273.59 }, { 229.00, 257.93 }, { 221.00, 255.48 }, { 215.00, 251.59 }, { 210.79, 246.00 }, { 207.47, 234.00 }, { 203.25, 227.00 }, { 179.00, 205.90 },
252     { 148.00, 189.54 }, { 136.00, 181.45 }, { 120.00, 180.31 }, { 110.00, 181.65 }, { 95.00, 179.31 }, { 63.00, 166.96 }, { 50.00, 164.23 }, { 31.00, 154.49 }, { 19.76, 145.00 }, { 15.96, 136.00 }, { 16.65, 127.00 }, { 20.57, 120.00 },
253     { 28.00, 114.63 }, { 40.00, 113.67 }, { 65.00, 127.22 }, { 73.00, 128.69 }, { 81.96, 120.00 }, { 77.58, 103.00 }, { 78.18, 92.00 }, { 59.11, 77.00 }, { 52.00, 67.29 }, { 31.29, 55.00 }, { 25.67, 47.00 }, { 24.65, 37.00 },
254     { 27.82, 29.00 }, { 35.00, 22.55 }, { 44.00, 20.35 }, { 49.00, 20.81 }, { 61.00, 25.69 }, { 79.00, 37.81 }, { 88.00, 49.64 }, { 97.00, 56.65 }, { 109.00, 49.61 }, { 143.00, 38.96 }, { 197.00, 37.27 }, { 215.00, 35.30 },
255     { 222.00, 36.65 }, { 228.42, 41.00 }, { 233.30, 49.00 }, { 234.14, 57.00 }, { 231.00, 65.80 }, { 224.00, 72.38 }, { 218.00, 74.50 }, { 197.00, 76.62 }, { 145.00, 78.81 }, { 123.00, 87.41 }, { 117.59, 98.00 }, { 117.79, 104.00 },
256     { 119.00, 106.23 }, { 138.73, 120.00 }, { 148.00, 129.50 }, { 158.50, 149.00 }, { 203.93, 175.00 }, { 229.00, 196.60 }, { 238.16, 208.00 }, { 245.20, 221.00 }, { 275.45, 245.00 }, { 289.00, 263.24 }, { 303.60, 287.00 }, { 312.00, 291.57 },
257     { 339.25, 266.00 }, { 366.33, 226.00 }, { 363.43, 216.00 }, { 364.13, 206.00 }, { 353.00, 196.72 }, { 324.00, 181.05 }, { 307.00, 169.63 }, { 274.93, 156.00 }, { 256.00, 152.48 }, { 228.00, 145.13 }, { 221.09, 142.00 }, { 214.87, 135.00 },
258     { 212.67, 127.00 }, { 213.81, 119.00 }, { 219.32, 111.00 }, { 228.00, 106.52 }, { 236.00, 106.39 }, { 290.00, 119.40 }, { 299.33, 114.00 }, { 300.52, 109.00 }, { 300.30, 53.00 }, { 301.46, 47.00 }, { 305.00, 41.12 }, { 311.00, 36.37 },
259     { 317.00, 34.43 }, { 325.00, 34.81 }, { 334.90, 41.00 }, { 339.45, 50.00 }, { 339.82, 132.00 }, { 346.09, 139.00 }, { 350.00, 150.26 }, { 380.00, 167.38 }, { 393.00, 166.48 }, { 407.00, 155.54 }, { 430.00, 147.30 }, { 437.78, 135.00 },
260     { 433.13, 122.00 }, { 410.23, 78.00 }, { 401.59, 69.00 }, { 393.48, 56.00 }, { 392.80, 44.00 }, { 395.50, 38.00 }, { 401.00, 32.49 }, { 409.00, 29.41 }, { 420.00, 30.84 }, { 426.92, 36.00 }, { 432.32, 44.00 }, { 439.49, 51.00 },
261     { 470.13, 108.00 }, { 475.71, 124.00 }, { 483.00, 130.11 }, { 488.00, 139.43 }, { 529.00, 139.40 }, { 536.00, 132.52 }, { 543.73, 129.00 }, { 540.47, 115.00 }, { 541.11, 100.00 }, { 552.18, 68.00 }, { 553.78, 47.00 }, { 559.00, 39.76 },
262     { 567.00, 35.52 }, { 577.00, 35.45 }, { 585.00, 39.58 }, { 591.38, 50.00 }, { 591.67, 66.00 }, { 590.31, 79.00 }, { 579.76, 109.00 }, { 582.25, 119.00 }, { 583.66, 136.00 }, { 586.45, 143.00 }, { 586.44, 151.00 }, { 580.42, 168.00 },
263     { 577.15, 173.00 }, { 572.00, 177.13 }, { 564.00, 179.49 }, { 478.00, 178.81 }, { 443.00, 184.76 }, { 427.10, 190.00 }, { 424.00, 192.11 }, { 415.94, 209.00 }, { 408.82, 228.00 }, { 405.82, 241.00 }, { 411.00, 250.82 }, { 415.00, 251.50 },
264     { 428.00, 248.89 }, { 469.00, 246.29 }, { 505.00, 246.49 }, { 533.00, 243.60 }, { 541.87, 248.00 }, { 547.55, 256.00 }, { 548.48, 267.00 }, { 544.00, 276.00 }, { 534.00, 282.24 }, { 513.00, 285.46 }, { 468.00, 285.76 }, { 402.00, 291.70 },
265     { 392.00, 290.29 }, { 377.00, 294.46 }, { 367.00, 294.43 }, { 356.44, 304.00 }, { 354.22, 311.00 }, { 362.00, 321.36 }, { 390.00, 322.44 }, { 433.00, 330.16 }, { 467.00, 332.76 }, { 508.00, 347.64 }, { 522.00, 357.67 }, { 528.00, 354.46 },
266     { 536.00, 352.96 }, { 546.06, 336.00 }, { 553.47, 306.00 }, { 564.19, 282.00 }, { 567.84, 268.00 }, { 578.72, 246.00 }, { 585.00, 240.97 }, { 592.00, 238.91 }, { 600.00, 239.72 }, { 606.00, 242.82 }, { 612.36, 251.00 }, { 613.35, 263.00 },
267     { 588.75, 324.00 }, { 583.25, 350.00 }, { 572.12, 370.00 }, { 575.45, 378.00 }, { 575.20, 388.00 }, { 589.00, 393.81 }, { 599.20, 404.00 }, { 607.14, 416.00 }, { 609.96, 430.00 }, { 615.45, 441.00 }, { 613.44, 462.00 }, { 610.48, 469.00 },
268     { 603.00, 475.63 }, { 590.96, 479.00 },
269 ];
270 
271 immutable complex_terrain_count = complex_terrain_verts.length;
272 
273 cpSpace* init_ComplexTerrainCircles_1000()
274 {
275     cpSpace* space = BENCH_SPACE_NEW();
276     space.iterations    = 10;
277     space.gravity       = cpv(0, -100);
278     space.collisionSlop = 0.5f;
279 
280     cpVect offset = cpv(-320, -240);
281 
282     for (int i = 0; i < (complex_terrain_count - 1); i++)
283     {
284         cpVect a = complex_terrain_verts[i], b = complex_terrain_verts[i + 1];
285         cpSpaceAddShape(space, cpSegmentShapeNew(space.staticBody, cpvadd(a, offset), cpvadd(b, offset), 0.0f));
286     }
287 
288     for (int i = 0; i < 1000; i++)
289     {
290         cpFloat radius = 5.0f;
291         cpFloat mass   = radius * radius;
292         cpBody* body_   = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForCircle(mass, 0.0f, radius, cpvzero)));
293         body_.p = cpvadd(cpvmult(frand_unit_circle(), 180.0f), cpv(0.0f, 300.0f));
294 
295         cpShape* shape = cpSpaceAddShape(space, cpCircleShapeNew(body_, radius, cpvzero));
296         shape.e = 0.0f;
297         shape.u = 0.0f;
298     }
299 
300     return space;
301 }
302 
303 cpSpace* init_ComplexTerrainHexagons_1000()
304 {
305     cpSpace* space = BENCH_SPACE_NEW();
306     space.iterations    = 10;
307     space.gravity       = cpv(0, -100);
308     space.collisionSlop = 0.5f;
309 
310     cpVect offset = cpv(-320, -240);
311 
312     for (int i = 0; i < (complex_terrain_count - 1); i++)
313     {
314         cpVect a = complex_terrain_verts[i], b = complex_terrain_verts[i + 1];
315         cpSpaceAddShape(space, cpSegmentShapeNew(space.staticBody, cpvadd(a, offset), cpvadd(b, offset), 0.0f));
316     }
317 
318     cpFloat radius     = 5.0f;
319     cpVect  hexagon[6] = {};
320 
321     for (int i = 0; i < 6; i++)
322     {
323         cpFloat angle = -M_PI * 2.0f * i / 6.0f;
324         hexagon[i] = cpvmult(cpv(cos(angle), sin(angle)), radius - bevel);
325     }
326 
327     for (int i = 0; i < 1000; i++)
328     {
329         cpFloat mass = radius * radius;
330         cpBody* body_ = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForPoly(mass, 6, hexagon.ptr, cpvzero)));
331         body_.p = cpvadd(cpvmult(frand_unit_circle(), 180.0f), cpv(0.0f, 300.0f));
332 
333         cpShape* shape = cpSpaceAddShape(space, cpPolyShapeNew2(body_, 6, hexagon.ptr, cpvzero, bevel));
334         shape.e = 0.0f;
335         shape.u = 0.0f;
336     }
337 
338     return space;
339 }
340 
341 // BouncyTerrain
342 immutable cpVect[] bouncy_terrain_verts = [
343     { 537.18, 23.00 }, { 520.50, 36.00 }, { 501.53, 63.00 }, { 496.14, 76.00 }, { 498.86, 86.00 }, { 504.00, 90.51 }, { 508.00, 91.36 }, { 508.77, 84.00 }, { 513.00, 77.73 }, { 519.00, 74.48 }, { 530.00, 74.67 }, { 545.00, 54.65 },
344     { 554.00, 48.77 }, { 562.00, 46.39 }, { 568.00, 45.94 }, { 568.61, 47.00 }, { 567.94, 55.00 }, { 571.27, 64.00 }, { 572.92, 80.00 }, { 572.00, 81.39 }, { 563.00, 79.93 }, { 556.00, 82.69 }, { 551.49, 88.00 }, { 549.00, 95.76 },
345     { 538.00, 93.40 }, { 530.00, 102.38 }, { 523.00, 104.00 }, { 517.00, 103.02 }, { 516.22, 109.00 }, { 518.96, 116.00 }, { 526.00, 121.15 }, { 534.00, 116.48 }, { 543.00, 116.77 }, { 549.28, 121.00 }, { 554.00, 130.17 }, { 564.00, 125.67 },
346     { 575.60, 129.00 }, { 573.31, 121.00 }, { 567.77, 111.00 }, { 575.00, 106.47 }, { 578.51, 102.00 }, { 580.25, 95.00 }, { 577.98, 87.00 }, { 582.00, 85.71 }, { 597.00, 89.46 }, { 604.80, 95.00 }, { 609.28, 104.00 }, { 610.55, 116.00 },
347     { 609.30, 125.00 }, { 600.80, 142.00 }, { 597.31, 155.00 }, { 584.00, 167.23 }, { 577.86, 175.00 }, { 583.52, 184.00 }, { 582.64, 195.00 }, { 591.00, 196.56 }, { 597.81, 201.00 }, { 607.45, 219.00 }, { 607.51, 246.00 }, { 600.00, 275.46 },
348     { 588.00, 267.81 }, { 579.00, 264.91 }, { 557.00, 264.41 }, { 552.98, 259.00 }, { 548.00, 246.18 }, { 558.00, 247.12 }, { 565.98, 244.00 }, { 571.10, 237.00 }, { 571.61, 229.00 }, { 568.25, 222.00 }, { 562.00, 217.67 }, { 544.00, 213.93 },
349     { 536.73, 214.00 }, { 535.60, 204.00 }, { 539.69, 181.00 }, { 542.84, 171.00 }, { 550.43, 161.00 }, { 540.00, 156.27 }, { 536.62, 152.00 }, { 534.70, 146.00 }, { 527.00, 141.88 }, { 518.59, 152.00 }, { 514.51, 160.00 }, { 510.33, 175.00 },
350     { 519.38, 183.00 }, { 520.52, 194.00 }, { 516.00, 201.27 }, { 505.25, 206.00 }, { 507.57, 223.00 }, { 519.90, 260.00 }, { 529.00, 260.48 }, { 534.00, 262.94 }, { 538.38, 268.00 }, { 540.00, 275.00 }, { 537.06, 284.00 }, { 530.00, 289.23 },
351     { 520.00, 289.23 }, { 513.00, 284.18 }, { 509.71, 286.00 }, { 501.69, 298.00 }, { 501.56, 305.00 }, { 504.30, 311.00 }, { 512.00, 316.43 }, { 521.00, 316.42 }, { 525.67, 314.00 }, { 535.00, 304.98 }, { 562.00, 294.80 }, { 573.00, 294.81 },
352     { 587.52, 304.00 }, { 600.89, 310.00 }, { 596.96, 322.00 }, { 603.28, 327.00 }, { 606.52, 333.00 }, { 605.38, 344.00 }, { 597.65, 352.00 }, { 606.36, 375.00 }, { 607.16, 384.00 }, { 603.40, 393.00 }, { 597.00, 398.14 }, { 577.00, 386.15 },
353     { 564.35, 373.00 }, { 565.21, 364.00 }, { 562.81, 350.00 }, { 553.00, 346.06 }, { 547.48, 338.00 }, { 547.48, 330.00 }, { 550.00, 323.30 }, { 544.00, 321.53 }, { 537.00, 322.70 }, { 532.00, 326.23 }, { 528.89, 331.00 }, { 527.83, 338.00 },
354     { 533.02, 356.00 }, { 542.00, 360.73 }, { 546.68, 369.00 }, { 545.38, 379.00 }, { 537.58, 386.00 }, { 537.63, 388.00 }, { 555.00, 407.47 }, { 563.00, 413.52 }, { 572.57, 418.00 }, { 582.72, 426.00 }, { 578.00, 431.12 }, { 563.21, 440.00 },
355     { 558.00, 449.27 }, { 549.00, 452.94 }, { 541.00, 451.38 }, { 536.73, 448.00 }, { 533.00, 441.87 }, { 520.00, 437.96 }, { 514.00, 429.69 }, { 490.00, 415.15 }, { 472.89, 399.00 }, { 472.03, 398.00 }, { 474.00, 396.71 }, { 486.00, 393.61 },
356     { 492.00, 385.85 }, { 492.00, 376.15 }, { 489.04, 371.00 }, { 485.00, 368.11 }, { 480.00, 376.27 }, { 472.00, 379.82 }, { 463.00, 378.38 }, { 455.08, 372.00 }, { 446.00, 377.69 }, { 439.00, 385.24 }, { 436.61, 391.00 }, { 437.52, 404.00 },
357     { 440.00, 409.53 }, { 463.53, 433.00 }, { 473.80, 441.00 }, { 455.00, 440.30 }, { 443.00, 436.18 }, { 436.00, 431.98 }, { 412.00, 440.92 }, { 397.00, 442.46 }, { 393.59, 431.00 }, { 393.71, 412.00 }, { 400.00, 395.10 }, { 407.32, 387.00 },
358     { 408.54, 380.00 }, { 407.42, 375.00 }, { 403.97, 370.00 }, { 399.00, 366.74 }, { 393.00, 365.68 }, { 391.23, 374.00 }, { 387.00, 380.27 }, { 381.00, 383.52 }, { 371.56, 384.00 }, { 364.98, 401.00 }, { 362.96, 412.00 }, { 363.63, 435.00 },
359     { 345.00, 433.55 }, { 344.52, 442.00 }, { 342.06, 447.00 }, { 337.00, 451.38 }, { 330.00, 453.00 }, { 325.00, 452.23 }, { 318.00, 448.17 }, { 298.00, 453.70 }, { 284.00, 451.49 }, { 278.62, 449.00 }, { 291.47, 408.00 }, { 291.77, 398.00 },
360     { 301.00, 393.83 }, { 305.00, 393.84 }, { 305.60, 403.00 }, { 310.00, 409.47 }, { 318.00, 413.07 }, { 325.00, 412.40 }, { 332.31, 407.00 }, { 335.07, 400.00 }, { 334.40, 393.00 }, { 329.00, 385.69 }, { 319.00, 382.79 }, { 301.00, 389.23 },
361     { 289.00, 389.97 }, { 265.00, 389.82 }, { 251.00, 385.85 }, { 245.00, 389.23 }, { 239.00, 389.94 }, { 233.00, 388.38 }, { 226.00, 382.04 }, { 206.00, 374.75 }, { 206.00, 394.00 }, { 204.27, 402.00 }, { 197.00, 401.79 }, { 191.00, 403.49 },
362     { 186.53, 407.00 }, { 183.60, 412.00 }, { 183.60, 422.00 }, { 189.00, 429.31 }, { 196.00, 432.07 }, { 203.00, 431.40 }, { 209.47, 427.00 }, { 213.00, 419.72 }, { 220.00, 420.21 }, { 227.00, 418.32 }, { 242.00, 408.41 }, { 258.98, 409.00 },
363     { 250.00, 435.43 }, { 239.00, 438.78 }, { 223.00, 448.19 }, { 209.00, 449.70 }, { 205.28, 456.00 }, { 199.00, 460.23 }, { 190.00, 460.52 }, { 182.73, 456.00 }, { 178.00, 446.27 }, { 160.00, 441.42 }, { 148.35, 435.00 }, { 149.79, 418.00 },
364     { 157.72, 401.00 }, { 161.00, 396.53 }, { 177.00, 385.00 }, { 180.14, 380.00 }, { 181.11, 374.00 }, { 180.00, 370.52 }, { 170.00, 371.68 }, { 162.72, 368.00 }, { 158.48, 361.00 }, { 159.56, 349.00 }, { 154.00, 342.53 }, { 146.00, 339.85 },
365     { 136.09, 343.00 }, { 130.64, 351.00 }, { 131.74, 362.00 }, { 140.61, 374.00 }, { 130.68, 387.00 }, { 120.75, 409.00 }, { 118.09, 421.00 }, { 117.92, 434.00 }, { 100.00, 432.40 }, { 87.00, 427.48 }, { 81.59, 423.00 }, { 73.64, 409.00 },
366     { 72.57, 398.00 }, { 74.62, 386.00 }, { 78.80, 378.00 }, { 88.00, 373.43 }, { 92.49, 367.00 }, { 93.32, 360.00 }, { 91.30, 353.00 }, { 103.00, 342.67 }, { 109.00, 343.10 }, { 116.00, 340.44 }, { 127.33, 330.00 }, { 143.00, 327.24 },
367     { 154.30, 322.00 }, { 145.00, 318.06 }, { 139.77, 311.00 }, { 139.48, 302.00 }, { 144.95, 293.00 }, { 143.00, 291.56 }, { 134.00, 298.21 }, { 118.00, 300.75 }, { 109.40, 305.00 }, { 94.67, 319.00 }, { 88.00, 318.93 }, { 81.00, 321.69 },
368     { 67.24, 333.00 }, { 56.68, 345.00 }, { 53.00, 351.40 }, { 47.34, 333.00 }, { 50.71, 314.00 }, { 56.57, 302.00 }, { 68.00, 287.96 }, { 91.00, 287.24 }, { 110.00, 282.36 }, { 133.80, 271.00 }, { 147.34, 256.00 }, { 156.47, 251.00 },
369     { 157.26, 250.00 }, { 154.18, 242.00 }, { 154.48, 236.00 }, { 158.72, 229.00 }, { 166.71, 224.00 }, { 170.15, 206.00 }, { 170.19, 196.00 }, { 167.24, 188.00 }, { 160.00, 182.67 }, { 150.00, 182.66 }, { 143.60, 187.00 }, { 139.96, 195.00 },
370     { 139.50, 207.00 }, { 136.45, 221.00 }, { 136.52, 232.00 }, { 133.28, 238.00 }, { 129.00, 241.38 }, { 119.00, 243.07 }, { 115.00, 246.55 }, { 101.00, 253.16 }, { 86.00, 257.32 }, { 63.00, 259.24 }, { 57.00, 257.31 }, { 50.54, 252.00 },
371     { 47.59, 247.00 }, { 46.30, 240.00 }, { 47.58, 226.00 }, { 50.00, 220.57 }, { 58.00, 226.41 }, { 69.00, 229.17 }, { 79.00, 229.08 }, { 94.50, 225.00 }, { 100.21, 231.00 }, { 107.00, 233.47 }, { 107.48, 224.00 }, { 109.94, 219.00 },
372     { 115.00, 214.62 }, { 122.57, 212.00 }, { 116.00, 201.49 }, { 104.00, 194.57 }, { 90.00, 194.04 }, { 79.00, 198.21 }, { 73.00, 198.87 }, { 62.68, 191.00 }, { 62.58, 184.00 }, { 64.42, 179.00 }, { 75.00, 167.70 }, { 80.39, 157.00 },
373     { 68.79, 140.00 }, { 61.67, 126.00 }, { 61.47, 117.00 }, { 64.43, 109.00 }, { 63.10, 96.00 }, { 56.48, 82.00 }, { 48.00, 73.88 }, { 43.81, 66.00 }, { 43.81, 56.00 }, { 50.11, 46.00 }, { 59.00, 41.55 }, { 71.00, 42.64 },
374     { 78.00, 36.77 }, { 83.00, 34.75 }, { 99.00, 34.32 }, { 117.00, 38.92 }, { 133.00, 55.15 }, { 142.00, 50.70 }, { 149.74, 51.00 }, { 143.55, 68.00 }, { 153.28, 74.00 }, { 156.23, 79.00 }, { 157.00, 84.00 }, { 156.23, 89.00 },
375     { 153.28, 94.00 }, { 144.58, 99.00 }, { 151.52, 112.00 }, { 151.51, 124.00 }, { 150.00, 126.36 }, { 133.00, 130.25 }, { 126.71, 125.00 }, { 122.00, 117.25 }, { 114.00, 116.23 }, { 107.73, 112.00 }, { 104.48, 106.00 }, { 104.32, 99.00 },
376     { 106.94, 93.00 }, { 111.24, 89.00 }, { 111.60, 85.00 }, { 107.24, 73.00 }, { 102.00, 67.57 }, { 99.79, 67.00 }, { 99.23, 76.00 }, { 95.00, 82.27 }, { 89.00, 85.52 }, { 79.84, 86.00 }, { 86.73, 114.00 }, { 98.00, 136.73 },
377     { 99.00, 137.61 }, { 109.00, 135.06 }, { 117.00, 137.94 }, { 122.52, 146.00 }, { 122.94, 151.00 }, { 121.00, 158.58 }, { 134.00, 160.97 }, { 153.00, 157.45 }, { 171.30, 150.00 }, { 169.06, 142.00 }, { 169.77, 136.00 }, { 174.00, 129.73 },
378     { 181.46, 126.00 }, { 182.22, 120.00 }, { 182.20, 111.00 }, { 180.06, 101.00 }, { 171.28, 85.00 }, { 171.75, 80.00 }, { 182.30, 53.00 }, { 189.47, 50.00 }, { 190.62, 38.00 }, { 194.00, 33.73 }, { 199.00, 30.77 }, { 208.00, 30.48 },
379     { 216.00, 34.94 }, { 224.00, 31.47 }, { 240.00, 30.37 }, { 247.00, 32.51 }, { 249.77, 35.00 }, { 234.75, 53.00 }, { 213.81, 93.00 }, { 212.08, 99.00 }, { 213.00, 101.77 }, { 220.00, 96.77 }, { 229.00, 96.48 }, { 236.28, 101.00 },
380     { 240.00, 107.96 }, { 245.08, 101.00 }, { 263.00, 65.32 }, { 277.47, 48.00 }, { 284.00, 47.03 }, { 286.94, 41.00 }, { 292.00, 36.62 }, { 298.00, 35.06 }, { 304.00, 35.77 }, { 314.00, 43.81 }, { 342.00, 32.56 }, { 359.00, 31.32 },
381     { 365.00, 32.57 }, { 371.00, 36.38 }, { 379.53, 48.00 }, { 379.70, 51.00 }, { 356.00, 52.19 }, { 347.00, 54.74 }, { 344.38, 66.00 }, { 341.00, 70.27 }, { 335.00, 73.52 }, { 324.00, 72.38 }, { 317.00, 65.75 }, { 313.00, 67.79 },
382     { 307.57, 76.00 }, { 315.00, 78.62 }, { 319.28, 82.00 }, { 322.23, 87.00 }, { 323.00, 94.41 }, { 334.00, 92.49 }, { 347.00, 87.47 }, { 349.62, 80.00 }, { 353.00, 75.73 }, { 359.00, 72.48 }, { 366.00, 72.32 }, { 372.00, 74.94 },
383     { 377.00, 81.34 }, { 382.00, 83.41 }, { 392.00, 83.40 }, { 399.00, 79.15 }, { 404.00, 85.74 }, { 411.00, 85.06 }, { 417.00, 86.62 }, { 423.38, 93.00 }, { 425.05, 104.00 }, { 438.00, 110.35 }, { 450.00, 112.17 }, { 452.62, 103.00 },
384     { 456.00, 98.73 }, { 462.00, 95.48 }, { 472.00, 95.79 }, { 471.28, 92.00 }, { 464.00, 84.62 }, { 445.00, 80.39 }, { 436.00, 75.33 }, { 428.00, 68.46 }, { 419.00, 68.52 }, { 413.00, 65.27 }, { 408.48, 58.00 }, { 409.87, 46.00 },
385     { 404.42, 39.00 }, { 408.00, 33.88 }, { 415.00, 29.31 }, { 429.00, 26.45 }, { 455.00, 28.77 }, { 470.00, 33.81 }, { 482.00, 42.16 }, { 494.00, 46.85 }, { 499.65, 36.00 }, { 513.00, 25.95 }, { 529.00, 22.42 }, { 537.18, 23.00 },
386 ];
387 
388 immutable int bouncy_terrain_count = bouncy_terrain_verts.length;
389 
390 cpSpace* init_BouncyTerrainCircles_500()
391 {
392     cpSpace* space = BENCH_SPACE_NEW();
393     space.iterations = 10;
394 
395     cpVect offset = cpv(-320, -240);
396 
397     for (int i = 0; i < (bouncy_terrain_count - 1); i++)
398     {
399         cpVect a       = bouncy_terrain_verts[i], b = bouncy_terrain_verts[i + 1];
400         cpShape* shape = cpSpaceAddShape(space, cpSegmentShapeNew(space.staticBody, cpvadd(a, offset), cpvadd(b, offset), 0.0f));
401         shape.e = 1.0f;
402     }
403 
404     for (int i = 0; i < 500; i++)
405     {
406         cpFloat radius = 5.0f;
407         cpFloat mass   = radius * radius;
408         cpBody* body_   = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForCircle(mass, 0.0f, radius, cpvzero)));
409         body_.p = cpvadd(cpvmult(frand_unit_circle(), 130.0f), cpvzero);
410         body_.v = cpvmult(frand_unit_circle(), 50.0f);
411 
412         cpShape* shape = cpSpaceAddShape(space, cpCircleShapeNew(body_, radius, cpvzero));
413         shape.e = 1.0f;
414     }
415 
416     return space;
417 }
418 
419 cpSpace* init_BouncyTerrainHexagons_500()
420 {
421     cpSpace* space = BENCH_SPACE_NEW();
422     space.iterations = 10;
423 
424     cpVect offset = cpv(-320, -240);
425 
426     for (int i = 0; i < (bouncy_terrain_count - 1); i++)
427     {
428         cpVect a       = bouncy_terrain_verts[i], b = bouncy_terrain_verts[i + 1];
429         cpShape* shape = cpSpaceAddShape(space, cpSegmentShapeNew(space.staticBody, cpvadd(a, offset), cpvadd(b, offset), 0.0f));
430         shape.e = 1.0f;
431     }
432 
433     cpFloat radius     = 5.0f;
434     cpVect  hexagon[6] = {};
435 
436     for (int i = 0; i < 6; i++)
437     {
438         cpFloat angle = -M_PI * 2.0f * i / 6.0f;
439         hexagon[i] = cpvmult(cpv(cos(angle), sin(angle)), radius - bevel);
440     }
441 
442     for (int i = 0; i < 500; i++)
443     {
444         cpFloat mass = radius * radius;
445         cpBody* body_ = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForPoly(mass, 6, hexagon.ptr, cpvzero)));
446         body_.p = cpvadd(cpvmult(frand_unit_circle(), 130.0f), cpvzero);
447         body_.v = cpvmult(frand_unit_circle(), 50.0f);
448 
449         cpShape* shape = cpSpaceAddShape(space, cpPolyShapeNew2(body_, 6, hexagon.ptr, cpvzero, bevel));
450         shape.e = 1.0f;
451     }
452 
453     return space;
454 }
455 
456 // No collisions
457 
458 cpBool NoCollide_begin(cpArbiter* arb, cpSpace* space, void* data)
459 {
460     int x;
461     assert(x);
462     return cpTrue;
463 }
464 
465 cpSpace* init_NoCollide()
466 {
467     cpSpace* space = BENCH_SPACE_NEW();
468     space.iterations = 10;
469 
470     cpSpaceAddCollisionHandler(space, 2, 2, &NoCollide_begin, null, null, null, null);
471 
472     float radius = 4.5f;
473 
474     cpSpaceAddShape(space, cpSegmentShapeNew(space.staticBody, cpv(-330 - radius, -250 - radius), cpv(330 + radius, -250 - radius), 0.0f)).e = 1.0f;
475     cpSpaceAddShape(space, cpSegmentShapeNew(space.staticBody, cpv(330 + radius, 250 + radius), cpv(330 + radius, -250 - radius), 0.0f)).e   = 1.0f;
476     cpSpaceAddShape(space, cpSegmentShapeNew(space.staticBody, cpv(330 + radius, 250 + radius), cpv(-330 - radius, 250 + radius), 0.0f)).e   = 1.0f;
477     cpSpaceAddShape(space, cpSegmentShapeNew(space.staticBody, cpv(-330 - radius, -250 - radius), cpv(-330 - radius, 250 + radius), 0.0f)).e = 1.0f;
478 
479     for (int x = -320; x <= 320; x += 20)
480     {
481         for (int y = -240; y <= 240; y += 20)
482         {
483             cpSpaceAddShape(space, cpCircleShapeNew(space.staticBody, radius, cpv(x, y)));
484         }
485     }
486 
487     for (int y = 10 - 240; y <= 240; y += 40)
488     {
489         cpFloat mass = 7.0f;
490         cpBody* body_ = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForCircle(mass, 0.0f, radius, cpvzero)));
491         body_.p = cpv(-320.0f, y);
492         body_.v = cpv(100.0f, 0.0f);
493 
494         cpShape* shape = cpSpaceAddShape(space, cpCircleShapeNew(body_, radius, cpvzero));
495         shape.e = 1.0f;
496         shape.collision_type = 2;
497     }
498 
499     for (int x = 30 - 320; x <= 320; x += 40)
500     {
501         cpFloat mass = 7.0f;
502         cpBody* body_ = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForCircle(mass, 0.0f, radius, cpvzero)));
503         body_.p = cpv(x, -240.0f);
504         body_.v = cpv(0.0f, 100.0f);
505 
506         cpShape* shape = cpSpaceAddShape(space, cpCircleShapeNew(body_, radius, cpvzero));
507         shape.e = 1.0f;
508         shape.collision_type = 2;
509     }
510 
511     return space;
512 }
513 
514 // TODO ideas:
515 // addition/removal
516 // Memory usage? (too small to matter?)
517 // http://forums.tigsource.com/index.php?topic=18077.msg518578#msg518578
518 
519 // Build benchmark list
520 void update(cpSpace* space, double dt)
521 {
522     BENCH_SPACE_STEP(space, dt);
523 }
524 
525 void destroy(cpSpace* space)
526 {
527     ChipmunkDemoFreeSpaceChildren(space);
528     BENCH_SPACE_FREE(space);
529 }
530 
531 // Make a second demo declaration for this demo to use in the regular demo set.
532 ChipmunkDemo BouncyHexagons = {
533     "Bouncy Hexagons",
534     1.0 / 60.0,
535     &init_BouncyTerrainHexagons_500,
536     &update,
537     &ChipmunkDemoDefaultDrawImpl,
538     &destroy,
539 };
540 
541 immutable ChipmunkDemo[] bench_list = [
542 	{"benchmark - " "SimpleTerrainCircles_1000", 1.0/60.0, &init_SimpleTerrainCircles_1000, &update, &ChipmunkDemoDefaultDrawImpl, &destroy},
543 	{"benchmark - " "SimpleTerrainCircles_500", 1.0/60.0, &init_SimpleTerrainCircles_500, &update, &ChipmunkDemoDefaultDrawImpl, &destroy},
544 	{"benchmark - " "SimpleTerrainCircles_100", 1.0/60.0, &init_SimpleTerrainCircles_100, &update, &ChipmunkDemoDefaultDrawImpl, &destroy},
545 	{"benchmark - " "SimpleTerrainBoxes_1000", 1.0/60.0, &init_SimpleTerrainBoxes_1000, &update, &ChipmunkDemoDefaultDrawImpl, &destroy},
546 	{"benchmark - " "SimpleTerrainBoxes_500", 1.0/60.0, &init_SimpleTerrainBoxes_500, &update, &ChipmunkDemoDefaultDrawImpl, &destroy},
547 	{"benchmark - " "SimpleTerrainBoxes_100", 1.0/60.0, &init_SimpleTerrainBoxes_100, &update, &ChipmunkDemoDefaultDrawImpl, &destroy},
548 	{"benchmark - " "SimpleTerrainHexagons_1000", 1.0/60.0, &init_SimpleTerrainHexagons_1000, &update, &ChipmunkDemoDefaultDrawImpl, &destroy},
549 	{"benchmark - " "SimpleTerrainHexagons_500", 1.0/60.0, &init_SimpleTerrainHexagons_500, &update, &ChipmunkDemoDefaultDrawImpl, &destroy},
550 	{"benchmark - " "SimpleTerrainHexagons_100", 1.0/60.0, &init_SimpleTerrainHexagons_100, &update, &ChipmunkDemoDefaultDrawImpl, &destroy},
551 	{"benchmark - " "SimpleTerrainVCircles_200", 1.0/60.0, &init_SimpleTerrainVCircles_200, &update, &ChipmunkDemoDefaultDrawImpl, &destroy},
552 	{"benchmark - " "SimpleTerrainVBoxes_200", 1.0/60.0, &init_SimpleTerrainVBoxes_200, &update, &ChipmunkDemoDefaultDrawImpl, &destroy},
553 	{"benchmark - " "SimpleTerrainVHexagons_200", 1.0/60.0, &init_SimpleTerrainVHexagons_200, &update, &ChipmunkDemoDefaultDrawImpl, &destroy},
554 	{"benchmark - " "ComplexTerrainCircles_1000", 1.0/60.0, &init_ComplexTerrainCircles_1000, &update, &ChipmunkDemoDefaultDrawImpl, &destroy},
555 	{"benchmark - " "ComplexTerrainHexagons_1000", 1.0/60.0, &init_ComplexTerrainHexagons_1000, &update, &ChipmunkDemoDefaultDrawImpl, &destroy},
556 	{"benchmark - " "BouncyTerrainCircles_500", 1.0/60.0, &init_BouncyTerrainCircles_500, &update, &ChipmunkDemoDefaultDrawImpl, &destroy},
557 	{"benchmark - " "BouncyTerrainHexagons_500", 1.0/60.0, &init_BouncyTerrainHexagons_500, &update, &ChipmunkDemoDefaultDrawImpl, &destroy},
558 	{"benchmark - " "NoCollide", 1.0/60.0, &init_NoCollide, &update, &ChipmunkDemoDefaultDrawImpl, &destroy},
559 ];
560 
561 immutable bench_count = bench_list.length;