0
|
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 */
|
2
|
31 module openmelee.render;
|
0
|
32
|
|
33 import xf.dog.Dog;
|
|
34 import xf.omg.core.LinearAlgebra;
|
|
35 import xf.hybrid.Event;
|
|
36 import xf.hybrid.Font;
|
|
37
|
2
|
38 import openmelee.melee;
|
0
|
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 {
|
6
|
95 const k_segments = 25.0f;
|
0
|
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();
|
2
|
320
|
|
321 float left = -screenSize.x / zoom;
|
|
322 float right = screenSize.x / zoom;
|
|
323 float bottom = -screenSize.y / zoom;
|
|
324 float top = screenSize.y / zoom;
|
|
325
|
|
326 gl.gluOrtho2D(left, right, bottom, top);
|
0
|
327 gl.Translatef(-viewCenter.x, -viewCenter.y, 0);
|
|
328 gl.MatrixMode(GL_MODELVIEW);
|
|
329 gl.Disable(GL_DEPTH_TEST);
|
|
330 gl.LoadIdentity();
|
|
331 gl.Clear(GL_COLOR_BUFFER_BIT);
|
|
332
|
|
333 // Draw dynamic bodies
|
|
334 if (settings.drawShapes) {
|
|
335 for (bzBody b = world.bodyList; b; b = b.next) {
|
|
336 for (bzShape shape = b.shapeList; shape; shape = shape.next) {
|
|
337
|
|
338 bzShape s = shape;
|
|
339 bzXForm xf = b.xf;
|
|
340
|
|
341 if (b.isStatic) {
|
|
342 gl.drawShape(s, xf, Color(0.5f, 0.9f, 0.5f), settings.drawCoreShapes);
|
|
343 }else if (b.isSleeping) {
|
|
344 gl.drawShape(s, xf, Color(0.5f, 0.5f, 0.9f), settings.drawCoreShapes);
|
|
345 }else if (b.userData) {
|
|
346 auto ss = cast(Select)b.userData;
|
|
347 if (ss) {
|
|
348 gl.drawShape(s, xf, Color(0, .5, 1), settings.drawCoreShapes);
|
|
349 }
|
|
350 }else {
|
|
351 gl.drawShape(s, xf, Color(0.9f, 0.9f, 0.9f), settings.drawCoreShapes);
|
|
352 }
|
|
353
|
|
354 gl.LoadIdentity();
|
|
355 gl.Flush();
|
|
356 }
|
|
357 }
|
|
358
|
|
359 // Draw water
|
|
360 bzFluidParticle[] particles = world.particles;
|
|
361 gl.Color3f(0, 0, 1);
|
|
362 foreach (p; particles) {
|
|
363 gl.drawCircle(vec2.from(p.position), WATER_RADIUS, true);
|
|
364 }
|
|
365 }
|
|
366
|
|
367 // Draw joints
|
|
368 if (settings.drawJoints) {
|
|
369 Color color = Color(0, 0, 1);
|
|
370 gl.Color3f(0, 0, 1);
|
|
371
|
|
372 gl.LineWidth(1);
|
|
373 for (bzJoint joint = world.jointList; joint; joint = joint.next) {
|
|
374 auto distance = cast(bzDistanceJoint)joint;
|
|
375 auto pulley = cast(bzPulleyJoint)joint;
|
|
376 auto revolute = cast(bzRevoluteJoint)joint;
|
|
377 auto prismatic = cast(bzPrismaticJoint)joint;
|
|
378 auto line = cast(bzLineJoint)joint;
|
|
379 if (distance) {
|
|
380 color = Color(.5, .5, 0);
|
|
381 // Endpoints
|
|
382 vec2 a = vec2.from(distance.anchor1);
|
|
383 vec2 b = vec2.from(distance.anchor2);
|
|
384 // Circles
|
|
385 gl.drawCircle(a, HINGE_RADIUS);
|
|
386 gl.drawCircle(b, HINGE_RADIUS);
|
|
387 // Connecting line
|
|
388 gl.connectCircles(a, HINGE_RADIUS, b, HINGE_RADIUS);
|
|
389 }else if (pulley) {
|
|
390 auto a = vec2.from(pulley.anchor1);
|
|
391 auto b = vec2.from(pulley.groundAnchor1);
|
|
392 auto c = vec2.from(pulley.groundAnchor2);
|
|
393 auto d = vec2.from(pulley.anchor2);
|
|
394 gl.drawCircle(a, HINGE_RADIUS);
|
|
395 gl.drawCircle(b, HINGE_RADIUS);
|
|
396 gl.connectCircles(a, HINGE_RADIUS, b, HINGE_RADIUS);
|
|
397 gl.drawSegment(b, c, color);
|
|
398 gl.drawCircle(c, HINGE_RADIUS);
|
|
399 gl.drawCircle(d, HINGE_RADIUS);
|
|
400 gl.connectCircles(c, HINGE_RADIUS, d, HINGE_RADIUS);
|
|
401 }else if (revolute) {
|
|
402 auto a = vec2.from(revolute.rBody1.position);
|
|
403 auto b = vec2.from(revolute.anchor1);
|
|
404 auto c = vec2.from(revolute.rBody2.position);
|
|
405 gl.drawCircle(a, HINGE_RADIUS);
|
|
406 gl.drawCircle(b, HINGE_RADIUS);
|
|
407 gl.connectCircles(a, HINGE_RADIUS, b, HINGE_RADIUS);
|
|
408 gl.drawCircle(c, HINGE_RADIUS);
|
|
409 gl.connectCircles(b, HINGE_RADIUS, c, HINGE_RADIUS);
|
|
410 }else if (prismatic) {
|
|
411 auto a = vec2.from(prismatic.rBody1.position);
|
|
412 auto b = vec2.from(prismatic.anchor1);
|
|
413 auto c = vec2.from(prismatic.rBody2.position);
|
|
414 gl.drawCircle(a, HINGE_RADIUS);
|
|
415 gl.drawCircle(b, HINGE_RADIUS);
|
|
416 gl.connectCircles(a, HINGE_RADIUS, b, HINGE_RADIUS);
|
|
417 gl.drawCircle(c, HINGE_RADIUS);
|
|
418 gl.connectCircles(b, HINGE_RADIUS, c, HINGE_RADIUS);
|
|
419 }else if (line) {
|
|
420 auto a = vec2.from(line.rBody1.position);
|
|
421 auto b = vec2.from(line.anchor1);
|
|
422 auto c = vec2.from(line.rBody2.position);
|
|
423 gl.drawCircle(a, HINGE_RADIUS);
|
|
424 gl.drawCircle(b, HINGE_RADIUS);
|
|
425 gl.connectCircles(a, HINGE_RADIUS, b, HINGE_RADIUS);
|
|
426 gl.drawCircle(c, HINGE_RADIUS);
|
|
427 gl.connectCircles(b, HINGE_RADIUS, c, HINGE_RADIUS);
|
|
428 }
|
|
429 }
|
|
430
|
|
431 if (settings.drawControllers) {
|
|
432 bzForceGenerator[] forces = world.forces;
|
|
433 foreach (f; forces) {
|
|
434 auto spring1 = cast(bzSpring1) f;
|
|
435 auto spring2 = cast(bzSpring2) f;
|
|
436 auto buoyancy = cast(bzBuoyancy) f;
|
|
437
|
|
438 if (spring1) {
|
|
439 auto bungee1 = cast(bzBungee1)spring1;
|
|
440 if (bungee1) {
|
|
441 gl.Color3f(.5, .5, 0);
|
|
442 // Endpoints
|
|
443 vec2 a = vec2.from(bungee1.rBody.position);
|
|
444 vec2 b = vec2.from(bungee1.anchor);
|
|
445 // Circles
|
|
446 gl.drawCircle(a, HINGE_RADIUS);
|
|
447 gl.drawCircle(b, HINGE_RADIUS);
|
|
448 // Connecting line
|
|
449 gl.connectCircles(a, HINGE_RADIUS, b, HINGE_RADIUS);
|
|
450 }else {
|
|
451 uint zigs = 10;
|
|
452 auto anchor1 = vec2.from(spring1.anchor);
|
|
453 auto anchor2 = vec2.from(spring1.rBody.position);
|
|
454 gl.drawSpring(anchor1, anchor2, zigs);
|
|
455 }
|
|
456 }
|
|
457
|
|
458 if (spring2) {
|
|
459 auto bungee2 = cast(bzBungee2)spring2;
|
|
460 if (bungee2) {
|
|
461 gl.Color3f(.5, .5, 0);
|
|
462 // Endpoints
|
|
463 vec2 a = vec2.from(bungee2.rBody.position);
|
|
464 vec2 b = vec2.from(bungee2.otherBody.position);
|
|
465 // Circles
|
|
466 gl.drawCircle(a, HINGE_RADIUS);
|
|
467 gl.drawCircle(b, HINGE_RADIUS);
|
|
468 // Connecting line
|
|
469 gl.connectCircles(a, HINGE_RADIUS, b, HINGE_RADIUS);
|
|
470 }else {
|
|
471 uint zigs = 10;
|
|
472 auto anchor1 = vec2.from(spring2.otherBody.position);
|
|
473 auto anchor2 = vec2.from(spring2.rBody.position);
|
|
474 gl.drawSpring(anchor1, anchor2, zigs);
|
|
475 }
|
|
476 }
|
|
477
|
|
478 if(buoyancy) {
|
|
479 float plane = buoyancy.planeOffset;
|
|
480 vec2 p1 = vec2(-50, plane);
|
|
481 vec2 p2 = vec2(50, plane);
|
|
482 gl.drawSegment(p1, p2, color);
|
|
483 }
|
|
484 }
|
|
485 }
|
|
486 }
|
|
487
|
|
488 if(settings.drawPairs) {
|
|
489
|
|
490 bzBroadPhase bp = world.broadPhase;
|
|
491 bzVec2 invQ;
|
|
492 invQ.set(1.0f / bp.m_quantizationFactor.x, 1.0f / bp.m_quantizationFactor.y);
|
|
493 Color color = Color(0.9f, 0.9f, 0.3f);
|
|
494
|
|
495 const k_tableCapacity = bzPairManager.TABLE_CAPACITY;
|
|
496
|
|
497 for (int i = 0; i < k_tableCapacity; ++i)
|
|
498 {
|
|
499 ushort index = bp.m_pairManager.m_hashTable[i];
|
|
500 while (index < bp.m_pairManager.m_pairs.length)
|
|
501 {
|
|
502 if(index == bzPairManager.NULL_PROXY) {
|
|
503 break;
|
|
504 }
|
|
505 bzPair pair = bp.m_pairManager.m_pairs[index];
|
|
506 bzProxy p1 = bp.m_proxyPool[pair.proxyId1];
|
|
507 bzProxy p2 = bp.m_proxyPool[pair.proxyId2];
|
|
508
|
|
509 bzAABB b1, b2;
|
|
510 b1.lowerBound.x = bp.m_worldAABB.lowerBound.x + invQ.x * bp.m_bounds[0][p1.lowerBounds[0]].value;
|
|
511 b1.lowerBound.y = bp.m_worldAABB.lowerBound.y + invQ.y * bp.m_bounds[1][p1.lowerBounds[1]].value;
|
|
512 b1.upperBound.x = bp.m_worldAABB.lowerBound.x + invQ.x * bp.m_bounds[0][p1.upperBounds[0]].value;
|
|
513 b1.upperBound.y = bp.m_worldAABB.lowerBound.y + invQ.y * bp.m_bounds[1][p1.upperBounds[1]].value;
|
|
514 b2.lowerBound.x = bp.m_worldAABB.lowerBound.x + invQ.x * bp.m_bounds[0][p2.lowerBounds[0]].value;
|
|
515 b2.lowerBound.y = bp.m_worldAABB.lowerBound.y + invQ.y * bp.m_bounds[1][p2.lowerBounds[1]].value;
|
|
516 b2.upperBound.x = bp.m_worldAABB.lowerBound.x + invQ.x * bp.m_bounds[0][p2.upperBounds[0]].value;
|
|
517 b2.upperBound.y = bp.m_worldAABB.lowerBound.y + invQ.y * bp.m_bounds[1][p2.upperBounds[1]].value;
|
|
518
|
|
519 bzVec2 x1 = 0.5f * (b1.lowerBound + b1.upperBound);
|
|
520 bzVec2 x2 = 0.5f * (b2.lowerBound + b2.upperBound);
|
|
521
|
|
522 gl.drawSegment(vec2.from(x1),vec2.from(x2), color);
|
|
523
|
|
524 index = pair.next;
|
|
525 }
|
|
526 }
|
|
527 }
|
|
528
|
|
529 // Draw axis aligned bounding boxes (bzAABB)
|
|
530 if (settings.drawAABBs) {
|
|
531 bzBroadPhase bp = world.broadPhase;
|
|
532 bzVec2 worldLower = bp.m_worldAABB.lowerBound;
|
|
533 bzVec2 worldUpper = bp.m_worldAABB.upperBound;
|
|
534 Color color;
|
|
535 bzVec2 invQ;
|
|
536 invQ.set(1.0f / bp.m_quantizationFactor.x, 1.0f / bp.m_quantizationFactor.y);
|
|
537 color = Color(1.0f, 1.0f, 1.0f);
|
5
|
538
|
0
|
539 for (int i = 0; i < k_maxProxies; ++i) {
|
|
540 bzProxy p = bp.m_proxyPool[i];
|
|
541 if (!p.isValid) {
|
|
542 continue;
|
|
543 }
|
|
544
|
|
545 bzAABB b;
|
|
546 b.lowerBound.x = worldLower.x + invQ.x * bp.m_bounds[0][p.lowerBounds[0]].value;
|
|
547 b.lowerBound.y = worldLower.y + invQ.y * bp.m_bounds[1][p.lowerBounds[1]].value;
|
|
548 b.upperBound.x = worldLower.x + invQ.x * bp.m_bounds[0][p.upperBounds[0]].value;
|
|
549 b.upperBound.y = worldLower.y + invQ.y * bp.m_bounds[1][p.upperBounds[1]].value;
|
|
550
|
|
551 vec2 vs[4];
|
|
552 vs[0] = vec2(b.lowerBound.x, b.lowerBound.y);
|
|
553 vs[1] = vec2(b.upperBound.x, b.lowerBound.y);
|
|
554 vs[2] = vec2(b.upperBound.x, b.upperBound.y);
|
|
555 vs[3] = vec2(b.lowerBound.x, b.upperBound.y);
|
|
556
|
|
557 drawPolygon(gl, vs, color);
|
|
558 }
|
5
|
559
|
0
|
560 vec2 vs[4];
|
|
561 vs[0] = vec2(worldLower.x, worldLower.y);
|
|
562 vs[1] = vec2(worldUpper.x, worldLower.y);
|
|
563 vs[2] = vec2(worldUpper.x, worldUpper.y);
|
|
564 vs[3] = vec2(worldLower.x, worldUpper.y);
|
|
565
|
|
566 color = Color(0.3f, 0.9f, 0.9f);
|
|
567 drawPolygon(gl, vs, color);
|
|
568 }
|
|
569
|
|
570 // Draw contact points
|
|
571 if (settings.drawContactPoints) {
|
|
572 const k_axisScale = 0.3f;
|
|
573 const k_forceScale = 0.01f;
|
|
574
|
|
575
|
|
576 for (int i = 0; i < pointCount; ++i) {
|
|
577 ContactPoint point = points[i];
|
|
578 Color color;
|
|
579
|
|
580 if (point.state == ContactState.e_contactAdded) {
|
|
581 // Add
|
|
582 color = Color(0.3f, 0.95f, 0.3f);
|
|
583 vec2 p = vec2.from(point.position);
|
|
584 gl.drawPoint(p, 10.0f, color);
|
|
585 }else if (point.state == ContactState.e_contactPersisted) {
|
|
586 // Persist
|
|
587 color = Color(0.3f, 0.3f, 0.95f);
|
|
588 vec2 p = vec2.from(point.position);
|
|
589 gl.drawPoint(p, 5.0f, color);
|
|
590 }else {
|
|
591 // Remove
|
|
592 color = Color(0.95f, 0.3f, 0.3f);
|
|
593 vec2 p = vec2.from(point.position);
|
|
594 gl.drawPoint(p, 10.0f, color);
|
|
595 }
|
|
596
|
|
597 if (settings.drawContactNormals == 1) {
|
|
598 vec2 p1 = vec2.from(point.position);
|
|
599 vec2 p2 = p1 + k_axisScale * vec2.from(point.normal);
|
|
600 color = Color(0.4f, 0.9f, 0.4f);
|
|
601 gl.drawSegment(p1, p2, color);
|
|
602 }else if (settings.drawContactForces) { /*
|
|
603 vec2 p1 = vec2.from(point.position);
|
|
604 vec2 p2 = p1 + k_forceScale * vec2.from(point.normalForce * point.normal);
|
|
605 color = Color(0.9f, 0.9f, 0.3f);
|
|
606 gl.drawSegment(p1, p2, color);*/
|
|
607 }
|
|
608
|
|
609 if (settings.drawFrictionForces) { /*
|
|
610 vec2 tangent = vec2.from(bzCross(point.normal, 1.0f));
|
|
611 vec2 p1 = point.position;
|
|
612 vec2 p2 = p1 + k_forceScale * vec2.from(point.tangentForce) * tangent;
|
|
613 color = Color(0.9f, 0.9f, 0.3f);
|
|
614 gl.drawSegment(p1, p2, color); */
|
|
615 }
|
|
616 }
|
|
617 }
|
|
618
|
|
619 if (settings.drawOBBs) {
|
|
620 Color color = Color(0.5f, 0.3f, 0.5f);
|
|
621
|
|
622 for (bzBody b = world.bodyList; b; b = b.next) {
|
|
623 bzXForm xf = b.xf;
|
|
624 for (bzShape s = b.shapeList; s; s = s.next) {
|
|
625 if (s.type != bzShapeType.POLYGON) {
|
|
626 continue;
|
|
627 }
|
|
628
|
|
629 bzPolygon poly = cast(bzPolygon)s;
|
|
630 bzOBB obb = poly.obb;
|
|
631 bzVec2 h = obb.extents;
|
|
632 bzVec2 vs[4];
|
|
633 vs[0].set(-h.x, -h.y);
|
|
634 vs[1].set(h.x, -h.y);
|
|
635 vs[2].set(h.x, h.y);
|
|
636 vs[3].set(-h.x, h.y);
|
|
637
|
|
638 vec2[4] v;
|
|
639 for (int i = 0; i < 4; ++i) {
|
|
640 vs[i] = obb.center + bzMul(obb.R, vs[i]);
|
|
641 v[i] = vec2.from(bzMul(xf, vs[i]));
|
|
642 }
|
|
643
|
|
644 drawPolygon(gl, v, color);
|
|
645 }
|
|
646 }
|
|
647 }
|
|
648
|
|
649 if (settings.drawCOMs) {
|
|
650 for (bzBody b = world.bodyList; b; b = b.next) {
|
|
651 bzXForm xf = b.xf;
|
|
652 xf.position = b.worldCenter;
|
|
653 drawXForm(gl, xf);
|
|
654 }
|
|
655 }
|
|
656 }
|
|
657
|
|
658 }
|