The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

296 lines
8.0KB

  1. /*
  2. * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org
  3. *
  4. * This software is provided 'as-is', without any express or implied
  5. * warranty. In no event will the authors be held liable for any damages
  6. * arising from the use of this software.
  7. * Permission is granted to anyone to use this software for any purpose,
  8. * including commercial applications, and to alter it and redistribute it
  9. * freely, subject to the following restrictions:
  10. * 1. The origin of this software must not be misrepresented; you must not
  11. * claim that you wrote the original software. If you use this software
  12. * in a product, an acknowledgment in the product documentation would be
  13. * appreciated but is not required.
  14. * 2. Altered source versions must be plainly marked as such, and must not be
  15. * misrepresented as being the original software.
  16. * 3. This notice may not be removed or altered from any source distribution.
  17. */
  18. #ifndef POLY_SHAPES_H
  19. #define POLY_SHAPES_H
  20. /// This tests stacking. It also shows how to use b2World::Query
  21. /// and b2TestOverlap.
  22. const int32 k_maxBodies = 256;
  23. /// This callback is called by b2World::QueryAABB. We find all the fixtures
  24. /// that overlap an AABB. Of those, we use b2TestOverlap to determine which fixtures
  25. /// overlap a circle. Up to 4 overlapped fixtures will be highlighted with a yellow border.
  26. class PolyShapesCallback : public b2QueryCallback
  27. {
  28. public:
  29. enum
  30. {
  31. e_maxCount = 4
  32. };
  33. PolyShapesCallback()
  34. {
  35. m_count = 0;
  36. }
  37. void DrawFixture(b2Fixture* fixture)
  38. {
  39. b2Color color(0.95f, 0.95f, 0.6f);
  40. const b2Transform& xf = fixture->GetBody()->GetTransform();
  41. switch (fixture->GetType())
  42. {
  43. case b2Shape::e_circle:
  44. {
  45. b2CircleShape* circle = (b2CircleShape*)fixture->GetShape();
  46. b2Vec2 center = b2Mul(xf, circle->m_p);
  47. float32 radius = circle->m_radius;
  48. m_debugDraw->DrawCircle(center, radius, color);
  49. }
  50. break;
  51. case b2Shape::e_polygon:
  52. {
  53. b2PolygonShape* poly = (b2PolygonShape*)fixture->GetShape();
  54. int32 vertexCount = poly->m_vertexCount;
  55. b2Assert(vertexCount <= b2_maxPolygonVertices);
  56. b2Vec2 vertices[b2_maxPolygonVertices];
  57. for (int32 i = 0; i < vertexCount; ++i)
  58. {
  59. vertices[i] = b2Mul(xf, poly->m_vertices[i]);
  60. }
  61. m_debugDraw->DrawPolygon(vertices, vertexCount, color);
  62. }
  63. break;
  64. default:
  65. break;
  66. }
  67. }
  68. /// Called for each fixture found in the query AABB.
  69. /// @return false to terminate the query.
  70. bool ReportFixture(b2Fixture* fixture)
  71. {
  72. if (m_count == e_maxCount)
  73. {
  74. return false;
  75. }
  76. b2Body* body = fixture->GetBody();
  77. b2Shape* shape = fixture->GetShape();
  78. bool overlap = b2TestOverlap(shape, 0, &m_circle, 0, body->GetTransform(), m_transform);
  79. if (overlap)
  80. {
  81. DrawFixture(fixture);
  82. ++m_count;
  83. }
  84. return true;
  85. }
  86. b2CircleShape m_circle;
  87. b2Transform m_transform;
  88. b2Draw* m_debugDraw;
  89. int32 m_count;
  90. };
  91. class PolyShapes : public Test
  92. {
  93. public:
  94. PolyShapes()
  95. {
  96. // Ground body
  97. {
  98. b2BodyDef bd;
  99. b2Body* ground = m_world->CreateBody(&bd);
  100. b2EdgeShape shape;
  101. shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f));
  102. ground->CreateFixture(&shape, 0.0f);
  103. }
  104. {
  105. b2Vec2 vertices[3];
  106. vertices[0].Set(-0.5f, 0.0f);
  107. vertices[1].Set(0.5f, 0.0f);
  108. vertices[2].Set(0.0f, 1.5f);
  109. m_polygons[0].Set(vertices, 3);
  110. }
  111. {
  112. b2Vec2 vertices[3];
  113. vertices[0].Set(-0.1f, 0.0f);
  114. vertices[1].Set(0.1f, 0.0f);
  115. vertices[2].Set(0.0f, 1.5f);
  116. m_polygons[1].Set(vertices, 3);
  117. }
  118. {
  119. float32 w = 1.0f;
  120. float32 b = w / (2.0f + b2Sqrt(2.0f));
  121. float32 s = b2Sqrt(2.0f) * b;
  122. b2Vec2 vertices[8];
  123. vertices[0].Set(0.5f * s, 0.0f);
  124. vertices[1].Set(0.5f * w, b);
  125. vertices[2].Set(0.5f * w, b + s);
  126. vertices[3].Set(0.5f * s, w);
  127. vertices[4].Set(-0.5f * s, w);
  128. vertices[5].Set(-0.5f * w, b + s);
  129. vertices[6].Set(-0.5f * w, b);
  130. vertices[7].Set(-0.5f * s, 0.0f);
  131. m_polygons[2].Set(vertices, 8);
  132. }
  133. {
  134. m_polygons[3].SetAsBox(0.5f, 0.5f);
  135. }
  136. {
  137. m_circle.m_radius = 0.5f;
  138. }
  139. m_bodyIndex = 0;
  140. memset(m_bodies, 0, sizeof(m_bodies));
  141. }
  142. void Create(int32 index)
  143. {
  144. if (m_bodies[m_bodyIndex] != NULL)
  145. {
  146. m_world->DestroyBody(m_bodies[m_bodyIndex]);
  147. m_bodies[m_bodyIndex] = NULL;
  148. }
  149. b2BodyDef bd;
  150. bd.type = b2_dynamicBody;
  151. float32 x = RandomFloat(-2.0f, 2.0f);
  152. bd.position.Set(x, 10.0f);
  153. bd.angle = RandomFloat(-b2_pi, b2_pi);
  154. if (index == 4)
  155. {
  156. bd.angularDamping = 0.02f;
  157. }
  158. m_bodies[m_bodyIndex] = m_world->CreateBody(&bd);
  159. if (index < 4)
  160. {
  161. b2FixtureDef fd;
  162. fd.shape = m_polygons + index;
  163. fd.density = 1.0f;
  164. fd.friction = 0.3f;
  165. m_bodies[m_bodyIndex]->CreateFixture(&fd);
  166. }
  167. else
  168. {
  169. b2FixtureDef fd;
  170. fd.shape = &m_circle;
  171. fd.density = 1.0f;
  172. fd.friction = 0.3f;
  173. m_bodies[m_bodyIndex]->CreateFixture(&fd);
  174. }
  175. m_bodyIndex = (m_bodyIndex + 1) % k_maxBodies;
  176. }
  177. void DestroyBody()
  178. {
  179. for (int32 i = 0; i < k_maxBodies; ++i)
  180. {
  181. if (m_bodies[i] != NULL)
  182. {
  183. m_world->DestroyBody(m_bodies[i]);
  184. m_bodies[i] = NULL;
  185. return;
  186. }
  187. }
  188. }
  189. void Keyboard(unsigned char key)
  190. {
  191. switch (key)
  192. {
  193. case '1':
  194. case '2':
  195. case '3':
  196. case '4':
  197. case '5':
  198. Create(key - '1');
  199. break;
  200. case 'a':
  201. for (int32 i = 0; i < k_maxBodies; i += 2)
  202. {
  203. if (m_bodies[i])
  204. {
  205. bool active = m_bodies[i]->IsActive();
  206. m_bodies[i]->SetActive(!active);
  207. }
  208. }
  209. break;
  210. case 'd':
  211. DestroyBody();
  212. break;
  213. }
  214. }
  215. void Step(Settings* settings)
  216. {
  217. Test::Step(settings);
  218. PolyShapesCallback callback;
  219. callback.m_circle.m_radius = 2.0f;
  220. callback.m_circle.m_p.Set(0.0f, 1.1f);
  221. callback.m_transform.SetIdentity();
  222. callback.m_debugDraw = &m_debugDraw;
  223. b2AABB aabb;
  224. callback.m_circle.ComputeAABB(&aabb, callback.m_transform, 0);
  225. m_world->QueryAABB(&callback, aabb);
  226. b2Color color(0.4f, 0.7f, 0.8f);
  227. m_debugDraw.DrawCircle(callback.m_circle.m_p, callback.m_circle.m_radius, color);
  228. m_debugDraw.DrawString(5, m_textLine, "Press 1-5 to drop stuff");
  229. m_textLine += 15;
  230. m_debugDraw.DrawString(5, m_textLine, "Press 'a' to (de)activate some bodies");
  231. m_textLine += 15;
  232. m_debugDraw.DrawString(5, m_textLine, "Press 'd' to destroy a body");
  233. m_textLine += 15;
  234. }
  235. static Test* Create()
  236. {
  237. return new PolyShapes;
  238. }
  239. int32 m_bodyIndex;
  240. b2Body* m_bodies[k_maxBodies];
  241. b2PolygonShape m_polygons[4];
  242. b2CircleShape m_circle;
  243. };
  244. #endif