Mercurial > projects > openmelee
comparison render.d @ 0:c10bc63824e7
Initial commit!
author | zzzzrrr <mason.green@gmail.com> |
---|---|
date | Fri, 20 Mar 2009 06:41:25 -0400 |
parents | |
children | a40d066ebbd1 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:c10bc63824e7 |
---|---|
1 /* | |
2 * Copyright (c) 2009, Mason Green (zzzzrrr) | |
3 * Based on Box2D by Erin Catto, http://www.box2d.org | |
4 * | |
5 * All rights reserved. | |
6 * | |
7 * Redistribution and use in source and binary forms, with or without modification, | |
8 * are permitted provided that the following conditions are met: | |
9 * | |
10 * * Redistributions of source code must retain the above copyright notice, | |
11 * this list of conditions and the following disclaimer. | |
12 * * Redistributions in binary form must reproduce the above copyright notice, | |
13 * this list of conditions and the following disclaimer in the documentation | |
14 * and/or other materials provided with the distribution. | |
15 * * Neither the name of the polygonal nor the names of its contributors may be | |
16 * used to endorse or promote products derived from this software without specific | |
17 * prior written permission. | |
18 * | |
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | |
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
26 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
27 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
28 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
29 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
30 */ | |
31 module melee.render; | |
32 | |
33 import xf.dog.Dog; | |
34 import xf.omg.core.LinearAlgebra; | |
35 import xf.hybrid.Event; | |
36 import xf.hybrid.Font; | |
37 | |
38 import melee.melee; | |
39 | |
40 /// Color for drawing. Each value has the range [0,1]. | |
41 struct Color { | |
42 static Color opCall(float r, float g, float b) | |
43 { | |
44 Color u; | |
45 u.r = r; | |
46 u.g = g; | |
47 u.b = b; | |
48 return u; | |
49 } | |
50 | |
51 float r = 0; | |
52 float g = 0; | |
53 float b = 0; | |
54 } | |
55 | |
56 class Render : Melee | |
57 { | |
58 | |
59 this(Settings *settings) { | |
60 | |
61 super(settings); | |
62 } | |
63 | |
64 void drawCircle(GL gl, vec2 center, float radius, bool water = false, float theta = float.nan) | |
65 { | |
66 int segs = cast(int)(radius) + 20; | |
67 if (segs > MAX_CIRCLE_RES) segs = MAX_CIRCLE_RES; | |
68 double coef = 2.0 * PI / segs; | |
69 | |
70 auto realTheta = (theta <>= 0 ? theta : 0); | |
71 if (water) { | |
72 gl.immediate(GL_TRIANGLE_FAN, | |
73 { | |
74 gl.Vertex2fv(center.ptr); | |
75 for (int n = 0; n <= segs; n++) { | |
76 double rads = n * coef; | |
77 gl.Vertex2f(radius * cos(rads + realTheta) + center.x, radius * sin(rads + realTheta) + center.y); | |
78 } | |
79 }); | |
80 } | |
81 | |
82 gl.immediate(GL_LINE_STRIP, | |
83 { | |
84 for (int n = 0; n <= segs; n++) { | |
85 double rads = n * coef; | |
86 gl.Vertex2f(radius * cos(rads + realTheta) + center.x, radius * sin(rads + realTheta) + center.y); | |
87 } | |
88 if (theta <>= 0) | |
89 gl.Vertex2fv(center.ptr); | |
90 }); | |
91 } | |
92 | |
93 void drawSolidCircle(GL gl, vec2 center, float radius, vec2 axis, Color color) | |
94 { | |
95 const k_segments = 16.0f; | |
96 const k_increment = 2.0f * PI / k_segments; | |
97 float theta = 0.0f; | |
98 gl.Enable(GL_BLEND); | |
99 gl.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | |
100 gl.Color4f(0.5f * color.r, 0.5f * color.g, 0.5f * color.b, 0.5f); | |
101 gl.Begin(GL_TRIANGLE_FAN); | |
102 for (int i = 0; i < k_segments; ++i) { | |
103 vec2 v = center + radius * vec2(cos(theta), sin(theta)); | |
104 gl.Vertex2f(v.x, v.y); | |
105 theta += k_increment; | |
106 } | |
107 gl.End(); | |
108 gl.Disable(GL_BLEND); | |
109 | |
110 theta = 0.0f; | |
111 gl.Color4f(color.r, color.g, color.b, 1.0f); | |
112 gl.Begin(GL_LINE_LOOP); | |
113 for (int i = 0; i < k_segments; ++i) { | |
114 vec2 v = center + radius * vec2(cos(theta), sin(theta)); | |
115 gl.Vertex2f(v.x, v.y); | |
116 theta += k_increment; | |
117 } | |
118 gl.End(); | |
119 | |
120 vec2 p = center + radius * axis; | |
121 gl.Begin(GL_LINES); | |
122 gl.Vertex2f(center.x, center.y); | |
123 gl.Vertex2f(p.x, p.y); | |
124 gl.End(); | |
125 } | |
126 | |
127 void drawPolygon(GL gl, vec2[] glVerts, Color color) | |
128 { | |
129 gl.Color3f(color.r, color.g, color.b); | |
130 gl.immediate(GL_LINE_LOOP, | |
131 { | |
132 foreach (v; glVerts) | |
133 gl.Vertex2fv(v.ptr); | |
134 }); | |
135 } | |
136 | |
137 void drawSolidPolygon(GL gl, vec2[] vertices, Color color) | |
138 { | |
139 gl.Enable(GL_BLEND); | |
140 gl.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | |
141 gl.Color4f(0.5f * color.r, 0.5f * color.g, 0.5f * color.b, 0.5f); | |
142 gl.Begin(GL_TRIANGLE_FAN); | |
143 for (int i = 0; i < vertices.length; ++i) { | |
144 gl.Vertex2f(vertices[i].x, vertices[i].y); | |
145 } | |
146 gl.End(); | |
147 gl.Disable(GL_BLEND); | |
148 | |
149 gl.Color4f(color.r, color.g, color.b, 1.0f); | |
150 gl.Begin(GL_LINE_LOOP); | |
151 for (int i = 0; i < vertices.length; ++i) { | |
152 gl.Vertex2f(vertices[i].x, vertices[i].y); | |
153 } | |
154 gl.End(); | |
155 } | |
156 | |
157 | |
158 void drawPoint(GL gl, vec2 p, float size, Color color) | |
159 { | |
160 gl.Color3f(color.r, color.g, color.b); | |
161 gl.PointSize(size); | |
162 gl.Begin(GL_POINTS); | |
163 gl.Vertex2f(p.x, p.y); | |
164 gl.End(); | |
165 gl.PointSize(1.0f); | |
166 } | |
167 | |
168 void drawSegment(GL gl, vec2 begin, vec2 end, Color color) | |
169 { | |
170 gl.Color3f(color.r, color.g, color.b); | |
171 gl.immediate(GL_LINES, | |
172 { | |
173 gl.Vertex2fv(begin.ptr); | |
174 gl.Vertex2fv(end.ptr); | |
175 }); | |
176 } | |
177 | |
178 // TODO: handle inequal radii correctly | |
179 void connectCircles(GL gl, vec2 center1, float radius1, vec2 center2, float radius2) | |
180 { | |
181 auto d = center2 - center1; | |
182 if (!d.length) | |
183 return; | |
184 d *= (d.length - radius1) / d.length; | |
185 center1 += d; | |
186 center2 -= d; | |
187 gl.immediate(GL_LINES, | |
188 { | |
189 gl.Vertex2fv(center1.ptr); | |
190 gl.Vertex2fv(center2.ptr); | |
191 }); | |
192 } | |
193 | |
194 void drawXForm(GL gl, bzXForm xf) | |
195 { | |
196 bzVec2 p1 = xf.position, p2; | |
197 const k_axisScale = 0.4f; | |
198 | |
199 gl.Begin(GL_LINES); | |
200 { | |
201 gl.Color3f(1.0f, 0.0f, 0.0f); | |
202 gl.Vertex2f(p1.x, p1.y); | |
203 p2 = p1 + k_axisScale * xf.R.col1; | |
204 gl.Vertex2f(p2.x, p2.y); | |
205 | |
206 gl.Color3f(0.0f, 1.0f, 0.0f); | |
207 gl.Vertex2f(p1.x, p1.y); | |
208 p2 = p1 + k_axisScale * xf.R.col2; | |
209 gl.Vertex2f(p2.x, p2.y); | |
210 } | |
211 gl.End(); | |
212 } | |
213 | |
214 void drawSpring(GL gl, vec2 a, vec2 b, uint zigs) | |
215 { | |
216 zigs++; | |
217 | |
218 // Portion of length dedicated to connectors | |
219 const float connPart = 0.2; | |
220 | |
221 vec2 inc = (b - a) / (zigs); | |
222 // One step from a to b | |
223 vec2 zigLen = inc * (1 - connPart); | |
224 // Length of a connector | |
225 vec2 connLen = inc * (connPart / 2) * zigs; | |
226 // Width of a zig | |
227 vec2 zigWidth = (b - a).rotatedHalfPi.normalized; | |
228 gl.immediate(GL_LINE_STRIP, | |
229 { | |
230 gl.Vertex2fv(a.ptr); | |
231 | |
232 a += connLen; | |
233 gl.Vertex2fv(a.ptr); | |
234 | |
235 bool dir = true; | |
236 a += zigWidth / 2 + zigLen / 2; | |
237 for (int i = 0; i < zigs; i++) { | |
238 gl.Vertex2fv(a.ptr); | |
239 a += zigLen; | |
240 if (dir) { | |
241 a -= zigWidth; | |
242 }else { | |
243 a += zigWidth; | |
244 } | |
245 dir = !dir; | |
246 } | |
247 | |
248 gl.Vertex2fv((b - connLen).ptr); | |
249 gl.Vertex2fv(b.ptr); | |
250 }); | |
251 } | |
252 | |
253 void drawShape(GL gl, bzShape shape, bzXForm xf, Color color, bool core) | |
254 { | |
255 Color coreColor = Color(0.9f, 0.6f, 0.6f); | |
256 | |
257 switch (shape.type) { | |
258 case bzShapeType.CIRCLE: | |
259 auto circle = cast(bzCircle)shape; | |
260 | |
261 vec2 center = vec2.from(bzMul(xf, circle.localPosition)); | |
262 float radius = circle.radius; | |
263 vec2 axis = vec2.from(xf.R.col1); | |
264 | |
265 gl.drawSolidCircle(center, radius, axis, color); | |
266 | |
267 if (core) { | |
268 gl.Color3f(coreColor.r, coreColor.g, coreColor.b); | |
269 gl.drawCircle(center, radius - k_toiSlop); | |
270 } | |
271 break; | |
272 case bzShapeType.POLYGON: | |
273 { | |
274 bzPolygon poly = cast(bzPolygon)shape; | |
275 bzVec2[] vertices = poly.worldVertices; | |
276 vec2[] verts; | |
277 verts.length = vertices.length; | |
278 foreach (int i, v; vertices) { | |
279 verts[i] = vec2.from(v); | |
280 } | |
281 | |
282 gl.drawSolidPolygon(verts, color); | |
283 | |
284 if (core) { | |
285 bzVec2[] localCoreVertices = poly.coreVertices; | |
286 verts.length = localCoreVertices.length; | |
287 for (int i = 0; i < localCoreVertices.length; ++i) { | |
288 verts[i] = vec2.from(bzMul(xf, localCoreVertices[i])); | |
289 } | |
290 gl.drawPolygon(verts, coreColor); | |
291 } | |
292 } | |
293 break; | |
294 | |
295 case bzShapeType.EDGE: | |
296 { | |
297 bzEdge edge = cast(bzEdge)shape; | |
298 | |
299 vec2 p1 = vec2.from(bzMul(xf, edge.vertex1)); | |
300 vec2 p2 = vec2.from(bzMul(xf, edge.vertex2)); | |
301 gl.drawSegment(p1, p2, color); | |
302 | |
303 if (core) { | |
304 p1 = vec2.from(bzMul(xf, edge.coreVertex1)); | |
305 p2 = vec2.from(bzMul(xf, edge.coreVertex2)); | |
306 gl.drawSegment(p1, p2, coreColor); | |
307 } | |
308 } | |
309 break; | |
310 } | |
311 } | |
312 | |
313 void draw(vec2i screenSize, GL gl) | |
314 { | |
315 this.screenSize = screenSize; | |
316 | |
317 gl.LoadIdentity(); | |
318 gl.MatrixMode(GL_PROJECTION); | |
319 gl.LoadIdentity(); | |
320 // Left, right, bottom, top | |
321 gl.gluOrtho2D(-screenSize.x / zoom, screenSize.x / zoom, -screenSize.y / zoom, screenSize.y / zoom); | |
322 gl.Translatef(-viewCenter.x, -viewCenter.y, 0); | |
323 gl.MatrixMode(GL_MODELVIEW); | |
324 gl.Disable(GL_DEPTH_TEST); | |
325 gl.LoadIdentity(); | |
326 gl.Clear(GL_COLOR_BUFFER_BIT); | |
327 | |
328 // Draw dynamic bodies | |
329 if (settings.drawShapes) { | |
330 for (bzBody b = world.bodyList; b; b = b.next) { | |
331 for (bzShape shape = b.shapeList; shape; shape = shape.next) { | |
332 | |
333 bzShape s = shape; | |
334 bzXForm xf = b.xf; | |
335 | |
336 if (b.isStatic) { | |
337 gl.drawShape(s, xf, Color(0.5f, 0.9f, 0.5f), settings.drawCoreShapes); | |
338 }else if (b.isSleeping) { | |
339 gl.drawShape(s, xf, Color(0.5f, 0.5f, 0.9f), settings.drawCoreShapes); | |
340 }else if (b.userData) { | |
341 auto ss = cast(Select)b.userData; | |
342 if (ss) { | |
343 gl.drawShape(s, xf, Color(0, .5, 1), settings.drawCoreShapes); | |
344 } | |
345 }else { | |
346 gl.drawShape(s, xf, Color(0.9f, 0.9f, 0.9f), settings.drawCoreShapes); | |
347 } | |
348 | |
349 gl.LoadIdentity(); | |
350 gl.Flush(); | |
351 } | |
352 } | |
353 | |
354 // Draw water | |
355 bzFluidParticle[] particles = world.particles; | |
356 gl.Color3f(0, 0, 1); | |
357 foreach (p; particles) { | |
358 gl.drawCircle(vec2.from(p.position), WATER_RADIUS, true); | |
359 } | |
360 } | |
361 | |
362 // Draw joints | |
363 if (settings.drawJoints) { | |
364 Color color = Color(0, 0, 1); | |
365 gl.Color3f(0, 0, 1); | |
366 | |
367 gl.LineWidth(1); | |
368 for (bzJoint joint = world.jointList; joint; joint = joint.next) { | |
369 auto distance = cast(bzDistanceJoint)joint; | |
370 auto pulley = cast(bzPulleyJoint)joint; | |
371 auto revolute = cast(bzRevoluteJoint)joint; | |
372 auto prismatic = cast(bzPrismaticJoint)joint; | |
373 auto line = cast(bzLineJoint)joint; | |
374 if (distance) { | |
375 color = Color(.5, .5, 0); | |
376 // Endpoints | |
377 vec2 a = vec2.from(distance.anchor1); | |
378 vec2 b = vec2.from(distance.anchor2); | |
379 // Circles | |
380 gl.drawCircle(a, HINGE_RADIUS); | |
381 gl.drawCircle(b, HINGE_RADIUS); | |
382 // Connecting line | |
383 gl.connectCircles(a, HINGE_RADIUS, b, HINGE_RADIUS); | |
384 }else if (pulley) { | |
385 auto a = vec2.from(pulley.anchor1); | |
386 auto b = vec2.from(pulley.groundAnchor1); | |
387 auto c = vec2.from(pulley.groundAnchor2); | |
388 auto d = vec2.from(pulley.anchor2); | |
389 gl.drawCircle(a, HINGE_RADIUS); | |
390 gl.drawCircle(b, HINGE_RADIUS); | |
391 gl.connectCircles(a, HINGE_RADIUS, b, HINGE_RADIUS); | |
392 gl.drawSegment(b, c, color); | |
393 gl.drawCircle(c, HINGE_RADIUS); | |
394 gl.drawCircle(d, HINGE_RADIUS); | |
395 gl.connectCircles(c, HINGE_RADIUS, d, HINGE_RADIUS); | |
396 }else if (revolute) { | |
397 auto a = vec2.from(revolute.rBody1.position); | |
398 auto b = vec2.from(revolute.anchor1); | |
399 auto c = vec2.from(revolute.rBody2.position); | |
400 gl.drawCircle(a, HINGE_RADIUS); | |
401 gl.drawCircle(b, HINGE_RADIUS); | |
402 gl.connectCircles(a, HINGE_RADIUS, b, HINGE_RADIUS); | |
403 gl.drawCircle(c, HINGE_RADIUS); | |
404 gl.connectCircles(b, HINGE_RADIUS, c, HINGE_RADIUS); | |
405 }else if (prismatic) { | |
406 auto a = vec2.from(prismatic.rBody1.position); | |
407 auto b = vec2.from(prismatic.anchor1); | |
408 auto c = vec2.from(prismatic.rBody2.position); | |
409 gl.drawCircle(a, HINGE_RADIUS); | |
410 gl.drawCircle(b, HINGE_RADIUS); | |
411 gl.connectCircles(a, HINGE_RADIUS, b, HINGE_RADIUS); | |
412 gl.drawCircle(c, HINGE_RADIUS); | |
413 gl.connectCircles(b, HINGE_RADIUS, c, HINGE_RADIUS); | |
414 }else if (line) { | |
415 auto a = vec2.from(line.rBody1.position); | |
416 auto b = vec2.from(line.anchor1); | |
417 auto c = vec2.from(line.rBody2.position); | |
418 gl.drawCircle(a, HINGE_RADIUS); | |
419 gl.drawCircle(b, HINGE_RADIUS); | |
420 gl.connectCircles(a, HINGE_RADIUS, b, HINGE_RADIUS); | |
421 gl.drawCircle(c, HINGE_RADIUS); | |
422 gl.connectCircles(b, HINGE_RADIUS, c, HINGE_RADIUS); | |
423 } | |
424 } | |
425 | |
426 if (settings.drawControllers) { | |
427 bzForceGenerator[] forces = world.forces; | |
428 foreach (f; forces) { | |
429 auto spring1 = cast(bzSpring1) f; | |
430 auto spring2 = cast(bzSpring2) f; | |
431 auto buoyancy = cast(bzBuoyancy) f; | |
432 | |
433 if (spring1) { | |
434 auto bungee1 = cast(bzBungee1)spring1; | |
435 if (bungee1) { | |
436 gl.Color3f(.5, .5, 0); | |
437 // Endpoints | |
438 vec2 a = vec2.from(bungee1.rBody.position); | |
439 vec2 b = vec2.from(bungee1.anchor); | |
440 // Circles | |
441 gl.drawCircle(a, HINGE_RADIUS); | |
442 gl.drawCircle(b, HINGE_RADIUS); | |
443 // Connecting line | |
444 gl.connectCircles(a, HINGE_RADIUS, b, HINGE_RADIUS); | |
445 }else { | |
446 uint zigs = 10; | |
447 auto anchor1 = vec2.from(spring1.anchor); | |
448 auto anchor2 = vec2.from(spring1.rBody.position); | |
449 gl.drawSpring(anchor1, anchor2, zigs); | |
450 } | |
451 } | |
452 | |
453 if (spring2) { | |
454 auto bungee2 = cast(bzBungee2)spring2; | |
455 if (bungee2) { | |
456 gl.Color3f(.5, .5, 0); | |
457 // Endpoints | |
458 vec2 a = vec2.from(bungee2.rBody.position); | |
459 vec2 b = vec2.from(bungee2.otherBody.position); | |
460 // Circles | |
461 gl.drawCircle(a, HINGE_RADIUS); | |
462 gl.drawCircle(b, HINGE_RADIUS); | |
463 // Connecting line | |
464 gl.connectCircles(a, HINGE_RADIUS, b, HINGE_RADIUS); | |
465 }else { | |
466 uint zigs = 10; | |
467 auto anchor1 = vec2.from(spring2.otherBody.position); | |
468 auto anchor2 = vec2.from(spring2.rBody.position); | |
469 gl.drawSpring(anchor1, anchor2, zigs); | |
470 } | |
471 } | |
472 | |
473 if(buoyancy) { | |
474 float plane = buoyancy.planeOffset; | |
475 vec2 p1 = vec2(-50, plane); | |
476 vec2 p2 = vec2(50, plane); | |
477 gl.drawSegment(p1, p2, color); | |
478 } | |
479 } | |
480 } | |
481 } | |
482 | |
483 if(settings.drawPairs) { | |
484 | |
485 bzBroadPhase bp = world.broadPhase; | |
486 bzVec2 invQ; | |
487 invQ.set(1.0f / bp.m_quantizationFactor.x, 1.0f / bp.m_quantizationFactor.y); | |
488 Color color = Color(0.9f, 0.9f, 0.3f); | |
489 | |
490 const k_tableCapacity = bzPairManager.TABLE_CAPACITY; | |
491 | |
492 for (int i = 0; i < k_tableCapacity; ++i) | |
493 { | |
494 ushort index = bp.m_pairManager.m_hashTable[i]; | |
495 while (index < bp.m_pairManager.m_pairs.length) | |
496 { | |
497 if(index == bzPairManager.NULL_PROXY) { | |
498 break; | |
499 } | |
500 bzPair pair = bp.m_pairManager.m_pairs[index]; | |
501 bzProxy p1 = bp.m_proxyPool[pair.proxyId1]; | |
502 bzProxy p2 = bp.m_proxyPool[pair.proxyId2]; | |
503 | |
504 bzAABB b1, b2; | |
505 b1.lowerBound.x = bp.m_worldAABB.lowerBound.x + invQ.x * bp.m_bounds[0][p1.lowerBounds[0]].value; | |
506 b1.lowerBound.y = bp.m_worldAABB.lowerBound.y + invQ.y * bp.m_bounds[1][p1.lowerBounds[1]].value; | |
507 b1.upperBound.x = bp.m_worldAABB.lowerBound.x + invQ.x * bp.m_bounds[0][p1.upperBounds[0]].value; | |
508 b1.upperBound.y = bp.m_worldAABB.lowerBound.y + invQ.y * bp.m_bounds[1][p1.upperBounds[1]].value; | |
509 b2.lowerBound.x = bp.m_worldAABB.lowerBound.x + invQ.x * bp.m_bounds[0][p2.lowerBounds[0]].value; | |
510 b2.lowerBound.y = bp.m_worldAABB.lowerBound.y + invQ.y * bp.m_bounds[1][p2.lowerBounds[1]].value; | |
511 b2.upperBound.x = bp.m_worldAABB.lowerBound.x + invQ.x * bp.m_bounds[0][p2.upperBounds[0]].value; | |
512 b2.upperBound.y = bp.m_worldAABB.lowerBound.y + invQ.y * bp.m_bounds[1][p2.upperBounds[1]].value; | |
513 | |
514 bzVec2 x1 = 0.5f * (b1.lowerBound + b1.upperBound); | |
515 bzVec2 x2 = 0.5f * (b2.lowerBound + b2.upperBound); | |
516 | |
517 gl.drawSegment(vec2.from(x1),vec2.from(x2), color); | |
518 | |
519 index = pair.next; | |
520 } | |
521 } | |
522 } | |
523 | |
524 // Draw axis aligned bounding boxes (bzAABB) | |
525 if (settings.drawAABBs) { | |
526 bzBroadPhase bp = world.broadPhase; | |
527 bzVec2 worldLower = bp.m_worldAABB.lowerBound; | |
528 bzVec2 worldUpper = bp.m_worldAABB.upperBound; | |
529 Color color; | |
530 bzVec2 invQ; | |
531 invQ.set(1.0f / bp.m_quantizationFactor.x, 1.0f / bp.m_quantizationFactor.y); | |
532 color = Color(1.0f, 1.0f, 1.0f); | |
533 | |
534 for (int i = 0; i < k_maxProxies; ++i) { | |
535 bzProxy p = bp.m_proxyPool[i]; | |
536 if (!p.isValid) { | |
537 continue; | |
538 } | |
539 | |
540 bzAABB b; | |
541 b.lowerBound.x = worldLower.x + invQ.x * bp.m_bounds[0][p.lowerBounds[0]].value; | |
542 b.lowerBound.y = worldLower.y + invQ.y * bp.m_bounds[1][p.lowerBounds[1]].value; | |
543 b.upperBound.x = worldLower.x + invQ.x * bp.m_bounds[0][p.upperBounds[0]].value; | |
544 b.upperBound.y = worldLower.y + invQ.y * bp.m_bounds[1][p.upperBounds[1]].value; | |
545 | |
546 vec2 vs[4]; | |
547 vs[0] = vec2(b.lowerBound.x, b.lowerBound.y); | |
548 vs[1] = vec2(b.upperBound.x, b.lowerBound.y); | |
549 vs[2] = vec2(b.upperBound.x, b.upperBound.y); | |
550 vs[3] = vec2(b.lowerBound.x, b.upperBound.y); | |
551 | |
552 drawPolygon(gl, vs, color); | |
553 } | |
554 | |
555 vec2 vs[4]; | |
556 vs[0] = vec2(worldLower.x, worldLower.y); | |
557 vs[1] = vec2(worldUpper.x, worldLower.y); | |
558 vs[2] = vec2(worldUpper.x, worldUpper.y); | |
559 vs[3] = vec2(worldLower.x, worldUpper.y); | |
560 | |
561 color = Color(0.3f, 0.9f, 0.9f); | |
562 drawPolygon(gl, vs, color); | |
563 } | |
564 | |
565 // Draw contact points | |
566 if (settings.drawContactPoints) { | |
567 const k_axisScale = 0.3f; | |
568 const k_forceScale = 0.01f; | |
569 | |
570 | |
571 for (int i = 0; i < pointCount; ++i) { | |
572 ContactPoint point = points[i]; | |
573 Color color; | |
574 | |
575 if (point.state == ContactState.e_contactAdded) { | |
576 // Add | |
577 color = Color(0.3f, 0.95f, 0.3f); | |
578 vec2 p = vec2.from(point.position); | |
579 gl.drawPoint(p, 10.0f, color); | |
580 }else if (point.state == ContactState.e_contactPersisted) { | |
581 // Persist | |
582 color = Color(0.3f, 0.3f, 0.95f); | |
583 vec2 p = vec2.from(point.position); | |
584 gl.drawPoint(p, 5.0f, color); | |
585 }else { | |
586 // Remove | |
587 color = Color(0.95f, 0.3f, 0.3f); | |
588 vec2 p = vec2.from(point.position); | |
589 gl.drawPoint(p, 10.0f, color); | |
590 } | |
591 | |
592 if (settings.drawContactNormals == 1) { | |
593 vec2 p1 = vec2.from(point.position); | |
594 vec2 p2 = p1 + k_axisScale * vec2.from(point.normal); | |
595 color = Color(0.4f, 0.9f, 0.4f); | |
596 gl.drawSegment(p1, p2, color); | |
597 }else if (settings.drawContactForces) { /* | |
598 vec2 p1 = vec2.from(point.position); | |
599 vec2 p2 = p1 + k_forceScale * vec2.from(point.normalForce * point.normal); | |
600 color = Color(0.9f, 0.9f, 0.3f); | |
601 gl.drawSegment(p1, p2, color);*/ | |
602 } | |
603 | |
604 if (settings.drawFrictionForces) { /* | |
605 vec2 tangent = vec2.from(bzCross(point.normal, 1.0f)); | |
606 vec2 p1 = point.position; | |
607 vec2 p2 = p1 + k_forceScale * vec2.from(point.tangentForce) * tangent; | |
608 color = Color(0.9f, 0.9f, 0.3f); | |
609 gl.drawSegment(p1, p2, color); */ | |
610 } | |
611 } | |
612 } | |
613 | |
614 if (settings.drawOBBs) { | |
615 Color color = Color(0.5f, 0.3f, 0.5f); | |
616 | |
617 for (bzBody b = world.bodyList; b; b = b.next) { | |
618 bzXForm xf = b.xf; | |
619 for (bzShape s = b.shapeList; s; s = s.next) { | |
620 if (s.type != bzShapeType.POLYGON) { | |
621 continue; | |
622 } | |
623 | |
624 bzPolygon poly = cast(bzPolygon)s; | |
625 bzOBB obb = poly.obb; | |
626 bzVec2 h = obb.extents; | |
627 bzVec2 vs[4]; | |
628 vs[0].set(-h.x, -h.y); | |
629 vs[1].set(h.x, -h.y); | |
630 vs[2].set(h.x, h.y); | |
631 vs[3].set(-h.x, h.y); | |
632 | |
633 vec2[4] v; | |
634 for (int i = 0; i < 4; ++i) { | |
635 vs[i] = obb.center + bzMul(obb.R, vs[i]); | |
636 v[i] = vec2.from(bzMul(xf, vs[i])); | |
637 } | |
638 | |
639 drawPolygon(gl, v, color); | |
640 } | |
641 } | |
642 } | |
643 | |
644 if (settings.drawCOMs) { | |
645 for (bzBody b = world.bodyList; b; b = b.next) { | |
646 bzXForm xf = b.xf; | |
647 xf.position = b.worldCenter; | |
648 drawXForm(gl, xf); | |
649 } | |
650 } | |
651 | |
652 // Nonphysical stuffs | |
653 // Universal '.' cursor | |
654 gl.Color3f(1, 1, 1); | |
655 gl.immediate(GL_POINTS, | |
656 { | |
657 gl.Vertex2fv(mousePos.ptr); | |
658 }); | |
659 | |
660 pointCount = 0; | |
661 } | |
662 | |
663 } |