Box2DDebugDraw.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. #include "Box2DDebugDraw.h"
  2. #include "core/VideoDriver.h"
  3. #include "RenderState.h"
  4. #include "core/gl/VideoDriverGLES20.h"
  5. #include "core/gl/ShaderProgramGL.h"
  6. #include "Material.h"
  7. #include "STDMaterial.h"
  8. Box2DDraw::Box2DDraw(): _worldScale(1.0f), _world(0)
  9. {
  10. m_drawFlags = 0xffffffff;
  11. const char* vertexShaderData = "\
  12. uniform mediump mat4 projection;\
  13. attribute vec2 a_position;\
  14. void main() {\
  15. vec4 position = vec4(a_position, 0.0, 1.0);\
  16. gl_Position = projection * position;\
  17. }\
  18. ";
  19. const char* fragmentShaderData = "\
  20. uniform mediump vec4 color;\
  21. void main() { \
  22. gl_FragColor = color; \
  23. } \
  24. ";
  25. int vs = ShaderProgramGL::createShader(GL_VERTEX_SHADER, vertexShaderData, 0, 0);
  26. int fs = ShaderProgramGL::createShader(GL_FRAGMENT_SHADER, fragmentShaderData, 0, 0);
  27. int pr = ShaderProgramGL::createProgram(vs, fs, (VertexDeclarationGL*)IVideoDriver::instance->getVertexDeclaration(VERTEX_POSITION));
  28. _program = new ShaderProgramGL(pr);
  29. }
  30. Box2DDraw::~Box2DDraw()
  31. {
  32. delete _program;
  33. }
  34. void Box2DDraw::doRender(const RenderState& rs)
  35. {
  36. Material::setCurrent(0);
  37. IVideoDriver* driver = IVideoDriver::instance;
  38. _world->SetDebugDraw(this);
  39. driver->setShaderProgram(_program);
  40. Matrix m = Matrix(rs.transform) * STDMaterial::instance->getRenderer()->getViewProjection();
  41. driver->setUniform("projection", &m);
  42. glEnable(GL_BLEND);
  43. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  44. _world->DrawDebugData();
  45. _world->SetDebugDraw(0);
  46. }
  47. void Box2DDraw::DrawPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color)
  48. {
  49. createPolygonVertices(vertices, vertexCount);
  50. drawPrimitives(false, true, vertexCount, color);
  51. }
  52. /// Draw a solid closed polygon provided in CCW order.
  53. void Box2DDraw::DrawSolidPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color)
  54. {
  55. createPolygonVertices(vertices, vertexCount);
  56. drawPrimitives(true, true, vertexCount, color);
  57. }
  58. /// Draw a circle.
  59. void Box2DDraw::DrawCircle(const b2Vec2& center, float32 aRadius, const b2Color& color)
  60. {
  61. createCircleVertices(center, aRadius);
  62. drawPrimitives(false, true, CIRCLE_SEGMENTS, color);
  63. }
  64. /// Draw a solid circle.
  65. void Box2DDraw::DrawSolidCircle(const b2Vec2& center, float32 aRadius, const b2Vec2& aAxis,
  66. const b2Color& color)
  67. {
  68. createCircleVertices(center, aRadius);
  69. drawPrimitives(true, true, CIRCLE_SEGMENTS, color);
  70. // Draw the axis line
  71. DrawSegment(center, center + aRadius * aAxis, color);
  72. }
  73. /// Draw a line segment.
  74. void Box2DDraw::DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color)
  75. {
  76. mVertices[0].x = p1.x * _worldScale;
  77. mVertices[0].y = p1.y * _worldScale;
  78. mVertices[1].x = p2.x * _worldScale;
  79. mVertices[1].y = p2.y * _worldScale;
  80. drawPrimitives(false, true, 2, color);
  81. }
  82. /// Draw a transform. Choose your own length scale.
  83. /// @param xf a transform.
  84. void Box2DDraw::DrawTransform(const b2Transform& xf)
  85. {
  86. b2Vec2 p1 = xf.p, p2;
  87. const float32 k_axisScale = 0.4f;
  88. p2 = p1 + k_axisScale * xf.q.GetXAxis();
  89. DrawSegment(p1, p2, b2Color(1, 0, 0));
  90. p2 = p1 + k_axisScale * xf.q.GetYAxis();
  91. DrawSegment(p1, p2, b2Color(0, 1, 0));
  92. }
  93. void Box2DDraw::createCircleVertices(const b2Vec2& center, float32 aRadius)
  94. {
  95. int vertexCount = 16;
  96. const float32 k_increment = 2.0f * b2_pi / CIRCLE_SEGMENTS;
  97. float32 theta = 0.0f;
  98. for (int32 i = 0; i < CIRCLE_SEGMENTS; ++i)
  99. {
  100. b2Vec2 v = center + aRadius * b2Vec2(scalar::cos(theta), scalar::sin(theta));
  101. mVertices[i].x = _worldScale * v.x;
  102. mVertices[i].y = _worldScale * v.y;
  103. theta += k_increment;
  104. }
  105. }
  106. void Box2DDraw::createPolygonVertices(const b2Vec2* vertices, int32 vertexCount)
  107. {
  108. if (vertexCount > MAX_VERTICES)
  109. {
  110. log::warning("need more vertices");
  111. return;
  112. }
  113. // convert vertices to screen resolution
  114. for (int i = 0; i < vertexCount; i++)
  115. {
  116. mVertices[i].x = _worldScale * vertices[i].x;
  117. mVertices[i].y = _worldScale * vertices[i].y;
  118. }
  119. }
  120. //------------------------------------------------------------------------
  121. void Box2DDraw::drawPrimitives(bool drawTriangles, bool drawLines, int count, const b2Color& color)
  122. {
  123. oxglEnableVertexAttribArray(0);
  124. oxglVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (GLfloat*)mVertices);
  125. if (drawTriangles)
  126. {
  127. Vector4 c(color.r, color.g, color.b, 0.5f);
  128. IVideoDriver::instance->setUniform("color", &c, 1);
  129. glDrawArrays(GL_TRIANGLE_FAN, 0, count);
  130. }
  131. if (drawLines)
  132. {
  133. Vector4 c(color.r, color.g, color.b, 1.0f);
  134. IVideoDriver::instance->setUniform("color", &c, 1);
  135. glDrawArrays(GL_LINE_LOOP, 0, count);
  136. }
  137. oxglDisableVertexAttribArray(0);
  138. }