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.

358 lines
9.3KB

  1. /*
  2. * Copyright (c) 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 DYNAMIC_TREE_TEST_H
  19. #define DYNAMIC_TREE_TEST_H
  20. class DynamicTreeTest : public Test
  21. {
  22. public:
  23. enum
  24. {
  25. e_actorCount = 128
  26. };
  27. DynamicTreeTest()
  28. {
  29. m_worldExtent = 15.0f;
  30. m_proxyExtent = 0.5f;
  31. srand(888);
  32. for (int32 i = 0; i < e_actorCount; ++i)
  33. {
  34. Actor* actor = m_actors + i;
  35. GetRandomAABB(&actor->aabb);
  36. actor->proxyId = m_tree.CreateProxy(actor->aabb, actor);
  37. }
  38. m_stepCount = 0;
  39. float32 h = m_worldExtent;
  40. m_queryAABB.lowerBound.Set(-3.0f, -4.0f + h);
  41. m_queryAABB.upperBound.Set(5.0f, 6.0f + h);
  42. m_rayCastInput.p1.Set(-5.0, 5.0f + h);
  43. m_rayCastInput.p2.Set(7.0f, -4.0f + h);
  44. //m_rayCastInput.p1.Set(0.0f, 2.0f + h);
  45. //m_rayCastInput.p2.Set(0.0f, -2.0f + h);
  46. m_rayCastInput.maxFraction = 1.0f;
  47. m_automated = false;
  48. }
  49. static Test* Create()
  50. {
  51. return new DynamicTreeTest;
  52. }
  53. void Step(Settings* settings)
  54. {
  55. B2_NOT_USED(settings);
  56. m_rayActor = NULL;
  57. for (int32 i = 0; i < e_actorCount; ++i)
  58. {
  59. m_actors[i].fraction = 1.0f;
  60. m_actors[i].overlap = false;
  61. }
  62. if (m_automated == true)
  63. {
  64. int32 actionCount = b2Max(1, e_actorCount >> 2);
  65. for (int32 i = 0; i < actionCount; ++i)
  66. {
  67. Action();
  68. }
  69. }
  70. Query();
  71. RayCast();
  72. for (int32 i = 0; i < e_actorCount; ++i)
  73. {
  74. Actor* actor = m_actors + i;
  75. if (actor->proxyId == b2_nullNode)
  76. continue;
  77. b2Color c(0.9f, 0.9f, 0.9f);
  78. if (actor == m_rayActor && actor->overlap)
  79. {
  80. c.Set(0.9f, 0.6f, 0.6f);
  81. }
  82. else if (actor == m_rayActor)
  83. {
  84. c.Set(0.6f, 0.9f, 0.6f);
  85. }
  86. else if (actor->overlap)
  87. {
  88. c.Set(0.6f, 0.6f, 0.9f);
  89. }
  90. m_debugDraw.DrawAABB(&actor->aabb, c);
  91. }
  92. b2Color c(0.7f, 0.7f, 0.7f);
  93. m_debugDraw.DrawAABB(&m_queryAABB, c);
  94. m_debugDraw.DrawSegment(m_rayCastInput.p1, m_rayCastInput.p2, c);
  95. b2Color c1(0.2f, 0.9f, 0.2f);
  96. b2Color c2(0.9f, 0.2f, 0.2f);
  97. m_debugDraw.DrawPoint(m_rayCastInput.p1, 6.0f, c1);
  98. m_debugDraw.DrawPoint(m_rayCastInput.p2, 6.0f, c2);
  99. if (m_rayActor)
  100. {
  101. b2Color cr(0.2f, 0.2f, 0.9f);
  102. b2Vec2 p = m_rayCastInput.p1 + m_rayActor->fraction * (m_rayCastInput.p2 - m_rayCastInput.p1);
  103. m_debugDraw.DrawPoint(p, 6.0f, cr);
  104. }
  105. {
  106. int32 height = m_tree.GetHeight();
  107. m_debugDraw.DrawString(5, m_textLine, "dynamic tree height = %d", height);
  108. m_textLine += 15;
  109. }
  110. ++m_stepCount;
  111. }
  112. void Keyboard(unsigned char key)
  113. {
  114. switch (key)
  115. {
  116. case 'a':
  117. m_automated = !m_automated;
  118. break;
  119. case 'c':
  120. CreateProxy();
  121. break;
  122. case 'd':
  123. DestroyProxy();
  124. break;
  125. case 'm':
  126. MoveProxy();
  127. break;
  128. }
  129. }
  130. bool QueryCallback(int32 proxyId)
  131. {
  132. Actor* actor = (Actor*)m_tree.GetUserData(proxyId);
  133. actor->overlap = b2TestOverlap(m_queryAABB, actor->aabb);
  134. return true;
  135. }
  136. float32 RayCastCallback(const b2RayCastInput& input, int32 proxyId)
  137. {
  138. Actor* actor = (Actor*)m_tree.GetUserData(proxyId);
  139. b2RayCastOutput output;
  140. bool hit = actor->aabb.RayCast(&output, input);
  141. if (hit)
  142. {
  143. m_rayCastOutput = output;
  144. m_rayActor = actor;
  145. m_rayActor->fraction = output.fraction;
  146. return output.fraction;
  147. }
  148. return input.maxFraction;
  149. }
  150. private:
  151. struct Actor
  152. {
  153. b2AABB aabb;
  154. float32 fraction;
  155. bool overlap;
  156. int32 proxyId;
  157. };
  158. void GetRandomAABB(b2AABB* aabb)
  159. {
  160. b2Vec2 w; w.Set(2.0f * m_proxyExtent, 2.0f * m_proxyExtent);
  161. //aabb->lowerBound.x = -m_proxyExtent;
  162. //aabb->lowerBound.y = -m_proxyExtent + m_worldExtent;
  163. aabb->lowerBound.x = RandomFloat(-m_worldExtent, m_worldExtent);
  164. aabb->lowerBound.y = RandomFloat(0.0f, 2.0f * m_worldExtent);
  165. aabb->upperBound = aabb->lowerBound + w;
  166. }
  167. void MoveAABB(b2AABB* aabb)
  168. {
  169. b2Vec2 d;
  170. d.x = RandomFloat(-0.5f, 0.5f);
  171. d.y = RandomFloat(-0.5f, 0.5f);
  172. //d.x = 2.0f;
  173. //d.y = 0.0f;
  174. aabb->lowerBound += d;
  175. aabb->upperBound += d;
  176. b2Vec2 c0 = 0.5f * (aabb->lowerBound + aabb->upperBound);
  177. b2Vec2 min; min.Set(-m_worldExtent, 0.0f);
  178. b2Vec2 max; max.Set(m_worldExtent, 2.0f * m_worldExtent);
  179. b2Vec2 c = b2Clamp(c0, min, max);
  180. aabb->lowerBound += c - c0;
  181. aabb->upperBound += c - c0;
  182. }
  183. void CreateProxy()
  184. {
  185. for (int32 i = 0; i < e_actorCount; ++i)
  186. {
  187. int32 j = rand() % e_actorCount;
  188. Actor* actor = m_actors + j;
  189. if (actor->proxyId == b2_nullNode)
  190. {
  191. GetRandomAABB(&actor->aabb);
  192. actor->proxyId = m_tree.CreateProxy(actor->aabb, actor);
  193. return;
  194. }
  195. }
  196. }
  197. void DestroyProxy()
  198. {
  199. for (int32 i = 0; i < e_actorCount; ++i)
  200. {
  201. int32 j = rand() % e_actorCount;
  202. Actor* actor = m_actors + j;
  203. if (actor->proxyId != b2_nullNode)
  204. {
  205. m_tree.DestroyProxy(actor->proxyId);
  206. actor->proxyId = b2_nullNode;
  207. return;
  208. }
  209. }
  210. }
  211. void MoveProxy()
  212. {
  213. for (int32 i = 0; i < e_actorCount; ++i)
  214. {
  215. int32 j = rand() % e_actorCount;
  216. Actor* actor = m_actors + j;
  217. if (actor->proxyId == b2_nullNode)
  218. {
  219. continue;
  220. }
  221. b2AABB aabb0 = actor->aabb;
  222. MoveAABB(&actor->aabb);
  223. b2Vec2 displacement = actor->aabb.GetCenter() - aabb0.GetCenter();
  224. m_tree.MoveProxy(actor->proxyId, actor->aabb, displacement);
  225. return;
  226. }
  227. }
  228. void Action()
  229. {
  230. int32 choice = rand() % 20;
  231. switch (choice)
  232. {
  233. case 0:
  234. CreateProxy();
  235. break;
  236. case 1:
  237. DestroyProxy();
  238. break;
  239. default:
  240. MoveProxy();
  241. }
  242. }
  243. void Query()
  244. {
  245. m_tree.Query(this, m_queryAABB);
  246. for (int32 i = 0; i < e_actorCount; ++i)
  247. {
  248. if (m_actors[i].proxyId == b2_nullNode)
  249. {
  250. continue;
  251. }
  252. bool overlap = b2TestOverlap(m_queryAABB, m_actors[i].aabb);
  253. B2_NOT_USED(overlap);
  254. b2Assert(overlap == m_actors[i].overlap);
  255. }
  256. }
  257. void RayCast()
  258. {
  259. m_rayActor = NULL;
  260. b2RayCastInput input = m_rayCastInput;
  261. // Ray cast against the dynamic tree.
  262. m_tree.RayCast(this, input);
  263. // Brute force ray cast.
  264. Actor* bruteActor = NULL;
  265. b2RayCastOutput bruteOutput;
  266. for (int32 i = 0; i < e_actorCount; ++i)
  267. {
  268. if (m_actors[i].proxyId == b2_nullNode)
  269. {
  270. continue;
  271. }
  272. b2RayCastOutput output;
  273. bool hit = m_actors[i].aabb.RayCast(&output, input);
  274. if (hit)
  275. {
  276. bruteActor = m_actors + i;
  277. bruteOutput = output;
  278. input.maxFraction = output.fraction;
  279. }
  280. }
  281. if (bruteActor != NULL)
  282. {
  283. b2Assert(bruteOutput.fraction == m_rayCastOutput.fraction);
  284. }
  285. }
  286. float32 m_worldExtent;
  287. float32 m_proxyExtent;
  288. b2DynamicTree m_tree;
  289. b2AABB m_queryAABB;
  290. b2RayCastInput m_rayCastInput;
  291. b2RayCastOutput m_rayCastOutput;
  292. Actor* m_rayActor;
  293. Actor m_actors[e_actorCount];
  294. int32 m_stepCount;
  295. bool m_automated;
  296. };
  297. #endif