Mercurial > projects > chipmunkd
comparison trunk/tests/ChipmunkDemos/drawSpace.d @ 16:af2f61a96318
ported chipmunk demos
author | Extrawurst |
---|---|
date | Sat, 04 Dec 2010 02:02:29 +0100 |
parents | |
children | f897d96cc7c9 |
comparison
equal
deleted
inserted
replaced
15:df4ebc8add66 | 16:af2f61a96318 |
---|---|
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 module drawSpace; | |
22 | |
23 import derelict.opengl.gl; | |
24 | |
25 import chipmunkd.chipmunk; | |
26 | |
27 import std.math:PI; | |
28 import std.stdio; | |
29 | |
30 struct drawSpaceOptions { | |
31 int drawHash; | |
32 int drawBBs; | |
33 int drawShapes; | |
34 float collisionPointSize; | |
35 float bodyPointSize; | |
36 float lineThickness; | |
37 } | |
38 | |
39 /* | |
40 IMPORTANT - READ ME! | |
41 | |
42 This file sets up a simple interface that the individual demos can use to get | |
43 a Chipmunk space running and draw what's in it. In order to keep the Chipmunk | |
44 examples clean and simple, they contain no graphics code. All drawing is done | |
45 by accessing the Chipmunk structures at a very low level. It is NOT | |
46 recommended to write a game or application this way as it does not scale | |
47 beyond simple shape drawing and is very dependent on implementation details | |
48 about Chipmunk which may change with little to no warning. | |
49 */ | |
50 | |
51 enum float[3] LINE_COLOR = [0,0,0]; | |
52 enum float[3] COLLISION_COLOR = [1,0,0]; | |
53 enum float[3] BODY_COLOR = [0,0,1]; | |
54 | |
55 static void | |
56 glColor_from_pointer(void *ptr) | |
57 { | |
58 ulong val = cast(long)ptr; | |
59 | |
60 // hash the pointer up nicely | |
61 val = (val+0x7ed55d16) + (val<<12); | |
62 val = (val^0xc761c23c) ^ (val>>19); | |
63 val = (val+0x165667b1) + (val<<5); | |
64 val = (val+0xd3a2646c) ^ (val<<9); | |
65 val = (val+0xfd7046c5) + (val<<3); | |
66 val = (val^0xb55a4f09) ^ (val>>16); | |
67 | |
68 // GLfloat v = (GLfloat)val/(GLfloat)ULONG_MAX; | |
69 // v = 0.95f - v*0.15f; | |
70 // | |
71 // glColor3f(v, v, v); | |
72 | |
73 GLubyte r = (val>>0) & 0xFF; | |
74 GLubyte g = (val>>8) & 0xFF; | |
75 GLubyte b = (val>>16) & 0xFF; | |
76 | |
77 GLubyte max = r>g ? (r>b ? r : b) : (g>b ? g : b); | |
78 | |
79 const int mult = 127; | |
80 const int add = 63; | |
81 r = cast(ubyte)((r*mult)/max + add); | |
82 g = cast(ubyte)((g*mult)/max + add); | |
83 b = cast(ubyte)((b*mult)/max + add); | |
84 | |
85 glColor3ub(r, g, b); | |
86 } | |
87 | |
88 static void | |
89 glColor_for_shape(cpShape *shape, cpSpace *space) | |
90 { | |
91 cpBody *_body = shape._body; | |
92 if(_body){ | |
93 if(_body.node.next){ | |
94 GLfloat v = 0.25f; | |
95 glColor3f(v,v,v); | |
96 return; | |
97 } else if(_body.node.idleTime > space.sleepTimeThreshold) { | |
98 GLfloat v = 0.9f; | |
99 glColor3f(v,v,v); | |
100 return; | |
101 } | |
102 } | |
103 | |
104 glColor_from_pointer(shape); | |
105 } | |
106 | |
107 enum GLfloat[] circleVAR = [ | |
108 0.0000f, 1.0000f, | |
109 0.2588f, 0.9659f, | |
110 0.5000f, 0.8660f, | |
111 0.7071f, 0.7071f, | |
112 0.8660f, 0.5000f, | |
113 0.9659f, 0.2588f, | |
114 1.0000f, 0.0000f, | |
115 0.9659f, -0.2588f, | |
116 0.8660f, -0.5000f, | |
117 0.7071f, -0.7071f, | |
118 0.5000f, -0.8660f, | |
119 0.2588f, -0.9659f, | |
120 0.0000f, -1.0000f, | |
121 -0.2588f, -0.9659f, | |
122 -0.5000f, -0.8660f, | |
123 -0.7071f, -0.7071f, | |
124 -0.8660f, -0.5000f, | |
125 -0.9659f, -0.2588f, | |
126 -1.0000f, -0.0000f, | |
127 -0.9659f, 0.2588f, | |
128 -0.8660f, 0.5000f, | |
129 -0.7071f, 0.7071f, | |
130 -0.5000f, 0.8660f, | |
131 -0.2588f, 0.9659f, | |
132 0.0000f, 1.0000f, | |
133 0.0f, 0.0f, // For an extra line to see the rotation. | |
134 ]; | |
135 enum int circleVAR_count = circleVAR.length / 2; | |
136 | |
137 static void | |
138 drawCircleShape(cpBody *_body, cpCircleShape *circle, cpSpace *space) | |
139 { | |
140 glVertexPointer(2, GL_FLOAT, 0, circleVAR.ptr); | |
141 | |
142 glPushMatrix(); { | |
143 cpVect center = circle.tc; | |
144 glTranslatef(center.x, center.y, 0.0f); | |
145 glRotatef(_body.a*180.0f/PI, 0.0f, 0.0f, 1.0f); | |
146 glScalef(circle.r, circle.r, 1.0f); | |
147 | |
148 if(!circle.shape.sensor){ | |
149 glColor_for_shape(cast(cpShape *)circle, space); | |
150 glDrawArrays(GL_TRIANGLE_FAN, 0, circleVAR_count - 1); | |
151 } | |
152 | |
153 glColor3fv(LINE_COLOR.ptr); | |
154 glDrawArrays(GL_LINE_STRIP, 0, circleVAR_count); | |
155 } glPopMatrix(); | |
156 } | |
157 | |
158 enum GLfloat[] pillVAR = [ | |
159 0.0000f, 1.0000f, 1.0f, | |
160 0.2588f, 0.9659f, 1.0f, | |
161 0.5000f, 0.8660f, 1.0f, | |
162 0.7071f, 0.7071f, 1.0f, | |
163 0.8660f, 0.5000f, 1.0f, | |
164 0.9659f, 0.2588f, 1.0f, | |
165 1.0000f, 0.0000f, 1.0f, | |
166 0.9659f, -0.2588f, 1.0f, | |
167 0.8660f, -0.5000f, 1.0f, | |
168 0.7071f, -0.7071f, 1.0f, | |
169 0.5000f, -0.8660f, 1.0f, | |
170 0.2588f, -0.9659f, 1.0f, | |
171 0.0000f, -1.0000f, 1.0f, | |
172 | |
173 0.0000f, -1.0000f, 0.0f, | |
174 -0.2588f, -0.9659f, 0.0f, | |
175 -0.5000f, -0.8660f, 0.0f, | |
176 -0.7071f, -0.7071f, 0.0f, | |
177 -0.8660f, -0.5000f, 0.0f, | |
178 -0.9659f, -0.2588f, 0.0f, | |
179 -1.0000f, -0.0000f, 0.0f, | |
180 -0.9659f, 0.2588f, 0.0f, | |
181 -0.8660f, 0.5000f, 0.0f, | |
182 -0.7071f, 0.7071f, 0.0f, | |
183 -0.5000f, 0.8660f, 0.0f, | |
184 -0.2588f, 0.9659f, 0.0f, | |
185 0.0000f, 1.0000f, 0.0f, | |
186 ]; | |
187 enum int pillVAR_count = pillVAR.length/3; | |
188 | |
189 static void | |
190 drawSegmentShape(cpBody *_body, cpSegmentShape *seg, cpSpace *space) | |
191 { | |
192 cpVect a = seg.ta; | |
193 cpVect b = seg.tb; | |
194 | |
195 if(seg.r){ | |
196 glVertexPointer(3, GL_FLOAT, 0, pillVAR.ptr); | |
197 glPushMatrix(); { | |
198 cpVect d = cpvsub(b, a); | |
199 cpVect r = cpvmult(d, seg.r/cpvlength(d)); | |
200 | |
201 GLfloat matrix[] = [ | |
202 r.x, r.y, 0.0f, 0.0f, | |
203 -r.y, r.x, 0.0f, 0.0f, | |
204 d.x, d.y, 0.0f, 0.0f, | |
205 a.x, a.y, 0.0f, 1.0f, | |
206 ]; | |
207 glMultMatrixf(matrix.ptr); | |
208 | |
209 if(!seg.shape.sensor){ | |
210 glColor_for_shape(cast(cpShape *)seg, space); | |
211 glDrawArrays(GL_TRIANGLE_FAN, 0, pillVAR_count); | |
212 } | |
213 | |
214 glColor3fv(LINE_COLOR.ptr); | |
215 glDrawArrays(GL_LINE_LOOP, 0, pillVAR_count); | |
216 } glPopMatrix(); | |
217 } else { | |
218 glColor3fv(LINE_COLOR.ptr); | |
219 glBegin(GL_LINES); { | |
220 glVertex2f(a.x, a.y); | |
221 glVertex2f(b.x, b.y); | |
222 } glEnd(); | |
223 } | |
224 } | |
225 | |
226 static void | |
227 drawPolyShape(cpBody *_body, cpPolyShape *poly, cpSpace *space) | |
228 { | |
229 int count = poly.numVerts; | |
230 version(CP_USE_DOUBLES) | |
231 { | |
232 glVertexPointer(2, GL_DOUBLE, 0, poly.tVerts); | |
233 } | |
234 else | |
235 { | |
236 glVertexPointer(2, GL_FLOAT, 0, poly.tVerts); | |
237 } | |
238 | |
239 if(!poly.shape.sensor){ | |
240 glColor_for_shape(cast(cpShape *)poly, space); | |
241 glDrawArrays(GL_TRIANGLE_FAN, 0, count); | |
242 } | |
243 | |
244 glColor3fv(LINE_COLOR.ptr); | |
245 glDrawArrays(GL_LINE_LOOP, 0, count); | |
246 } | |
247 | |
248 static void | |
249 drawObject(cpShape *shape, cpSpace *space) | |
250 { | |
251 cpBody *_body = shape._body; | |
252 | |
253 switch(shape.klass.type){ | |
254 case cpShapeType.CP_CIRCLE_SHAPE: | |
255 drawCircleShape(_body, cast(cpCircleShape *)shape, space); | |
256 break; | |
257 case cpShapeType.CP_SEGMENT_SHAPE: | |
258 drawSegmentShape(_body, cast(cpSegmentShape *)shape, space); | |
259 break; | |
260 case cpShapeType.CP_POLY_SHAPE: | |
261 drawPolyShape(_body, cast(cpPolyShape *)shape, space); | |
262 break; | |
263 default: | |
264 writefln("Bad enumeration in drawObject()."); | |
265 } | |
266 } | |
267 | |
268 enum GLfloat[] springVAR = [ | |
269 0.00f, 0.0f, | |
270 0.20f, 0.0f, | |
271 0.25f, 3.0f, | |
272 0.30f,-6.0f, | |
273 0.35f, 6.0f, | |
274 0.40f,-6.0f, | |
275 0.45f, 6.0f, | |
276 0.50f,-6.0f, | |
277 0.55f, 6.0f, | |
278 0.60f,-6.0f, | |
279 0.65f, 6.0f, | |
280 0.70f,-3.0f, | |
281 0.75f, 6.0f, | |
282 0.80f, 0.0f, | |
283 1.00f, 0.0f, | |
284 ]; | |
285 enum int springVAR_count = springVAR.length / 2; | |
286 | |
287 static void | |
288 drawSpring(cpDampedSpring *spring, cpBody *body_a, cpBody *body_b) | |
289 { | |
290 cpVect a = cpvadd(body_a.p, cpvrotate(spring.anchr1, body_a.rot)); | |
291 cpVect b = cpvadd(body_b.p, cpvrotate(spring.anchr2, body_b.rot)); | |
292 | |
293 glPointSize(5.0f); | |
294 glBegin(GL_POINTS); { | |
295 glVertex2f(a.x, a.y); | |
296 glVertex2f(b.x, b.y); | |
297 } glEnd(); | |
298 | |
299 cpVect delta = cpvsub(b, a); | |
300 | |
301 glVertexPointer(2, GL_FLOAT, 0, springVAR.ptr); | |
302 glPushMatrix(); { | |
303 GLfloat x = a.x; | |
304 GLfloat y = a.y; | |
305 GLfloat cos = delta.x; | |
306 GLfloat sin = delta.y; | |
307 GLfloat s = 1.0f/cpvlength(delta); | |
308 | |
309 GLfloat matrix[] = [ | |
310 cos, sin, 0.0f, 0.0f, | |
311 -sin*s, cos*s, 0.0f, 0.0f, | |
312 0.0f, 0.0f, 1.0f, 0.0f, | |
313 x, y, 0.0f, 1.0f, | |
314 ]; | |
315 | |
316 glMultMatrixf(matrix.ptr); | |
317 glDrawArrays(GL_LINE_STRIP, 0, springVAR_count); | |
318 } glPopMatrix(); | |
319 } | |
320 | |
321 static void | |
322 drawConstraint(cpConstraint *constraint) | |
323 { | |
324 cpBody *body_a = constraint.a; | |
325 cpBody *body_b = constraint.b; | |
326 | |
327 const cpConstraintClass *klass = constraint.klass; | |
328 if(klass == cpPinJointGetClass()){ | |
329 cpPinJoint *joint = cast(cpPinJoint *)constraint; | |
330 | |
331 cpVect a = cpvadd(body_a.p, cpvrotate(joint.anchr1, body_a.rot)); | |
332 cpVect b = cpvadd(body_b.p, cpvrotate(joint.anchr2, body_b.rot)); | |
333 | |
334 glPointSize(5.0f); | |
335 glBegin(GL_POINTS); { | |
336 glVertex2f(a.x, a.y); | |
337 glVertex2f(b.x, b.y); | |
338 } glEnd(); | |
339 | |
340 glBegin(GL_LINES); { | |
341 glVertex2f(a.x, a.y); | |
342 glVertex2f(b.x, b.y); | |
343 } glEnd(); | |
344 } else if(klass == cpSlideJointGetClass()){ | |
345 cpSlideJoint *joint = cast(cpSlideJoint *)constraint; | |
346 | |
347 cpVect a = cpvadd(body_a.p, cpvrotate(joint.anchr1, body_a.rot)); | |
348 cpVect b = cpvadd(body_b.p, cpvrotate(joint.anchr2, body_b.rot)); | |
349 | |
350 glPointSize(5.0f); | |
351 glBegin(GL_POINTS); { | |
352 glVertex2f(a.x, a.y); | |
353 glVertex2f(b.x, b.y); | |
354 } glEnd(); | |
355 | |
356 glBegin(GL_LINES); { | |
357 glVertex2f(a.x, a.y); | |
358 glVertex2f(b.x, b.y); | |
359 } glEnd(); | |
360 } else if(klass == cpPivotJointGetClass()){ | |
361 cpPivotJoint *joint = cast(cpPivotJoint *)constraint; | |
362 | |
363 cpVect a = cpvadd(body_a.p, cpvrotate(joint.anchr1, body_a.rot)); | |
364 cpVect b = cpvadd(body_b.p, cpvrotate(joint.anchr2, body_b.rot)); | |
365 | |
366 glPointSize(10.0f); | |
367 glBegin(GL_POINTS); { | |
368 glVertex2f(a.x, a.y); | |
369 glVertex2f(b.x, b.y); | |
370 } glEnd(); | |
371 } else if(klass == cpGrooveJointGetClass()){ | |
372 cpGrooveJoint *joint = cast(cpGrooveJoint *)constraint; | |
373 | |
374 cpVect a = cpvadd(body_a.p, cpvrotate(joint.grv_a, body_a.rot)); | |
375 cpVect b = cpvadd(body_a.p, cpvrotate(joint.grv_b, body_a.rot)); | |
376 cpVect c = cpvadd(body_b.p, cpvrotate(joint.anchr2, body_b.rot)); | |
377 | |
378 glPointSize(5.0f); | |
379 glBegin(GL_POINTS); { | |
380 glVertex2f(c.x, c.y); | |
381 } glEnd(); | |
382 | |
383 glBegin(GL_LINES); { | |
384 glVertex2f(a.x, a.y); | |
385 glVertex2f(b.x, b.y); | |
386 } glEnd(); | |
387 } else if(klass == cpDampedSpringGetClass()){ | |
388 drawSpring(cast(cpDampedSpring *)constraint, body_a, body_b); | |
389 } else { | |
390 // printf("Cannot draw constraint\n"); | |
391 } | |
392 } | |
393 | |
394 static void | |
395 drawBB(cpShape *shape, void *unused) | |
396 { | |
397 glBegin(GL_LINE_LOOP); { | |
398 glVertex2f(shape.bb.l, shape.bb.b); | |
399 glVertex2f(shape.bb.l, shape.bb.t); | |
400 glVertex2f(shape.bb.r, shape.bb.t); | |
401 glVertex2f(shape.bb.r, shape.bb.b); | |
402 } glEnd(); | |
403 } | |
404 | |
405 // copied from cpSpaceHash.c | |
406 static cpHashValue | |
407 hash_func(cpHashValue x, cpHashValue y, cpHashValue n) | |
408 { | |
409 return cast(cpHashValue)((x*1640531513uL ^ y*2654435789uL) % n); | |
410 } | |
411 | |
412 static void | |
413 drawSpatialHash(cpSpaceHash *hash) | |
414 { | |
415 cpBB bb = cpBBNew(-320, -240, 320, 240); | |
416 | |
417 cpFloat dim = hash.celldim; | |
418 int n = hash.numcells; | |
419 | |
420 int l = cast(int)floorf(bb.l/dim); | |
421 int r = cast(int)floorf(bb.r/dim); | |
422 int b = cast(int)floorf(bb.b/dim); | |
423 int t = cast(int)floorf(bb.t/dim); | |
424 | |
425 for(int i=l; i<=r; i++){ | |
426 for(int j=b; j<=t; j++){ | |
427 int cell_count = 0; | |
428 | |
429 int index = hash_func(i,j,n); | |
430 for(cpSpaceHashBin *bin = hash.table[index]; bin; bin = bin.next) | |
431 cell_count++; | |
432 | |
433 GLfloat v = 1.0f - cast(GLfloat)cell_count/10.0f; | |
434 glColor3f(v,v,v); | |
435 glRectf(i*dim, j*dim, (i + 1)*dim, (j + 1)*dim); | |
436 } | |
437 } | |
438 } | |
439 | |
440 void | |
441 DrawSpace(cpSpace *space, const drawSpaceOptions *options) | |
442 { | |
443 if(options.drawHash){ | |
444 glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_TRUE); | |
445 drawSpatialHash(space.activeShapes); | |
446 glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_FALSE); | |
447 drawSpatialHash(space.staticShapes); | |
448 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); | |
449 } | |
450 | |
451 glLineWidth(options.lineThickness); | |
452 if(options.drawShapes){ | |
453 cpSpaceHashEach(space.activeShapes, cast(cpSpaceHashIterator)&drawObject, space); | |
454 cpSpaceHashEach(space.staticShapes, cast(cpSpaceHashIterator)&drawObject, space); | |
455 } | |
456 | |
457 glLineWidth(1.0f); | |
458 if(options.drawBBs){ | |
459 glColor3f(0.3f, 0.5f, 0.3f); | |
460 cpSpaceHashEach(space.activeShapes, cast(cpSpaceHashIterator)&drawBB, null); | |
461 cpSpaceHashEach(space.staticShapes, cast(cpSpaceHashIterator)&drawBB, null); | |
462 } | |
463 | |
464 cpArray *constraints = space.constraints; | |
465 | |
466 glColor3f(0.5f, 1.0f, 0.5f); | |
467 for(int i=0, count = constraints.num; i<count; i++){ | |
468 drawConstraint(cast(cpConstraint *)constraints.arr[i]); | |
469 } | |
470 | |
471 if(options.bodyPointSize){ | |
472 glPointSize(options.bodyPointSize); | |
473 | |
474 glBegin(GL_POINTS); { | |
475 glColor3fv(LINE_COLOR.ptr); | |
476 cpArray *bodies = space.bodies; | |
477 for(int i=0, count = bodies.num; i<count; i++){ | |
478 cpBody *_body = cast(cpBody *)bodies.arr[i]; | |
479 glVertex2f(_body.p.x, _body.p.y); | |
480 } | |
481 | |
482 // glColor3f(0.5f, 0.5f, 0.5f); | |
483 // cpArray *components = space.components; | |
484 // for(int i=0; i<components.num; i++){ | |
485 // cpBody *root = components.arr[i]; | |
486 // cpBody *body = root, *next; | |
487 // do { | |
488 // next = body.node.next; | |
489 // glVertex2f(body.p.x, body.p.y); | |
490 // } while((body = next) != root); | |
491 // } | |
492 } glEnd(); | |
493 } | |
494 | |
495 if(options.collisionPointSize){ | |
496 glPointSize(options.collisionPointSize); | |
497 glBegin(GL_POINTS); { | |
498 cpArray *arbiters = space.arbiters; | |
499 for(int i=0; i<arbiters.num; i++){ | |
500 cpArbiter *arb = cast(cpArbiter*)arbiters.arr[i]; | |
501 | |
502 glColor3fv(COLLISION_COLOR.ptr); | |
503 foreach(j; 0..arb.numContacts){ | |
504 cpVect v = arb.contacts[j].p; | |
505 glVertex2f(v.x, v.y); | |
506 } | |
507 } | |
508 } glEnd(); | |
509 } | |
510 } |