DebugDrawer.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577
  1. #include "anki/renderer/DebugDrawer.h"
  2. #include "anki/resource/ShaderProgramResource.h"
  3. #include "anki/physics/Converters.h"
  4. #include "anki/collision/Collision.h"
  5. #include "anki/scene/Frustumable.h"
  6. #include "anki/scene/Octree.h"
  7. #include "anki/scene/Sector.h"
  8. #include "anki/resource/Material.h"
  9. #include "anki/scene/Renderable.h"
  10. #include "anki/scene/Camera.h"
  11. #include "anki/scene/ModelNode.h"
  12. #include "anki/resource/TextureResource.h"
  13. #include "anki/renderer/Renderer.h"
  14. namespace anki {
  15. //==============================================================================
  16. // DebugDrawer =
  17. //==============================================================================
  18. //==============================================================================
  19. DebugDrawer::DebugDrawer()
  20. {
  21. prog.load("shaders/Dbg.glsl");
  22. vbo.create(GL_ARRAY_BUFFER, sizeof(clientVerts), nullptr,
  23. GL_DYNAMIC_DRAW);
  24. vao.create();
  25. vao.attachArrayBufferVbo(
  26. &vbo, prog->findAttributeVariable("position"), 3, GL_FLOAT,
  27. false, sizeof(Vertex), 0);
  28. vao.attachArrayBufferVbo(
  29. &vbo, prog->findAttributeVariable("color"), 3, GL_FLOAT,
  30. false, sizeof(Vertex), sizeof(Vec4));
  31. GLint loc =
  32. prog->findAttributeVariable("modelViewProjectionMat").getLocation();
  33. vao.attachArrayBufferVbo(
  34. &vbo, loc, 4, GL_FLOAT, false, sizeof(Vertex),
  35. 2 * sizeof(Vec4));
  36. vao.attachArrayBufferVbo(
  37. &vbo, loc + 1, 4, GL_FLOAT, false, sizeof(Vertex),
  38. 3 * sizeof(Vec4));
  39. vao.attachArrayBufferVbo(
  40. &vbo, loc + 2, 4, GL_FLOAT, false, sizeof(Vertex),
  41. 4 * sizeof(Vec4));
  42. vao.attachArrayBufferVbo(
  43. &vbo, loc + 3, 4, GL_FLOAT, false, sizeof(Vertex),
  44. 5 * sizeof(Vec4));
  45. vertexPointer = 0;
  46. mMat.setIdentity();
  47. vpMat.setIdentity();
  48. mvpMat.setIdentity();
  49. crntCol = Vec3(1.0, 0.0, 0.0);
  50. }
  51. //==============================================================================
  52. DebugDrawer::~DebugDrawer()
  53. {}
  54. //==============================================================================
  55. void DebugDrawer::setModelMatrix(const Mat4& m)
  56. {
  57. mMat = m;
  58. mvpMat = vpMat * mMat;
  59. }
  60. //==============================================================================
  61. void DebugDrawer::setViewProjectionMatrix(const Mat4& m)
  62. {
  63. vpMat = m;
  64. mvpMat = vpMat * mMat;
  65. }
  66. //==============================================================================
  67. void DebugDrawer::begin()
  68. {
  69. // Do nothing. Keep for compatibility
  70. }
  71. //==============================================================================
  72. void DebugDrawer::end()
  73. {
  74. if(vertexPointer % 2 != 0)
  75. {
  76. // push back the previous vertex to close the loop
  77. pushBackVertex(clientVerts[vertexPointer].position.xyz());
  78. }
  79. }
  80. //==============================================================================
  81. void DebugDrawer::flush()
  82. {
  83. if(vertexPointer == 0)
  84. {
  85. // Early exit
  86. return;
  87. }
  88. vbo.write(&clientVerts[0], 0, sizeof(clientVerts));
  89. prog->bind();
  90. vao.bind();
  91. glDrawArrays(GL_LINES, 0, vertexPointer);
  92. vertexPointer = 0;
  93. }
  94. //==============================================================================
  95. void DebugDrawer::pushBackVertex(const Vec3& pos)
  96. {
  97. clientVerts[vertexPointer].position = Vec4(pos, 1.0);
  98. clientVerts[vertexPointer].color = Vec4(crntCol, 1.0);
  99. clientVerts[vertexPointer].matrix = mvpMat.getTransposed();
  100. ++vertexPointer;
  101. if(vertexPointer == MAX_POINTS_PER_DRAW)
  102. {
  103. flush();
  104. }
  105. }
  106. //==============================================================================
  107. void DebugDrawer::drawLine(const Vec3& from, const Vec3& to, const Vec4& color)
  108. {
  109. setColor(color);
  110. begin();
  111. pushBackVertex(from);
  112. pushBackVertex(to);
  113. end();
  114. }
  115. //==============================================================================
  116. void DebugDrawer::drawGrid()
  117. {
  118. Vec4 col0(0.5, 0.5, 0.5, 1.0);
  119. Vec4 col1(0.0, 0.0, 1.0, 1.0);
  120. Vec4 col2(1.0, 0.0, 0.0, 1.0);
  121. const F32 SPACE = 1.0; // space between lines
  122. const U NUM = 57; // lines number. must be odd
  123. const F32 GRID_HALF_SIZE = ((NUM - 1) * SPACE / 2);
  124. setColor(col0);
  125. begin();
  126. for(U x = - NUM / 2 * SPACE; x < NUM / 2 * SPACE; x += SPACE)
  127. {
  128. setColor(col0);
  129. // if the middle line then change color
  130. if(x == 0)
  131. {
  132. setColor(col1);
  133. }
  134. // line in z
  135. pushBackVertex(Vec3(x, 0.0, -GRID_HALF_SIZE));
  136. pushBackVertex(Vec3(x, 0.0, GRID_HALF_SIZE));
  137. // if middle line change col so you can highlight the x-axis
  138. if(x == 0)
  139. {
  140. setColor(col2);
  141. }
  142. // line in the x
  143. pushBackVertex(Vec3(-GRID_HALF_SIZE, 0.0, x));
  144. pushBackVertex(Vec3(GRID_HALF_SIZE, 0.0, x));
  145. }
  146. // render
  147. end();
  148. }
  149. //==============================================================================
  150. void DebugDrawer::drawSphere(F32 radius, int complexity)
  151. {
  152. Vector<Vec3>* sphereLines;
  153. // Pre-calculate the sphere points5
  154. //
  155. std::unordered_map<U32, Vector<Vec3>>::iterator it =
  156. complexityToPreCalculatedSphere.find(complexity);
  157. if(it != complexityToPreCalculatedSphere.end()) // Found
  158. {
  159. sphereLines = &(it->second);
  160. }
  161. else // Not found
  162. {
  163. complexityToPreCalculatedSphere[complexity] = Vector<Vec3>();
  164. sphereLines = &complexityToPreCalculatedSphere[complexity];
  165. F32 fi = getPi<F32>() / complexity;
  166. Vec3 prev(1.0, 0.0, 0.0);
  167. for(F32 th = fi; th < getPi<F32>() * 2.0 + fi; th += fi)
  168. {
  169. Vec3 p = Mat3(Euler(0.0, th, 0.0)) * Vec3(1.0, 0.0, 0.0);
  170. for(F32 th2 = 0.0; th2 < getPi<F32>(); th2 += fi)
  171. {
  172. Mat3 rot(Euler(th2, 0.0, 0.0));
  173. Vec3 rotPrev = rot * prev;
  174. Vec3 rotP = rot * p;
  175. sphereLines->push_back(rotPrev);
  176. sphereLines->push_back(rotP);
  177. Mat3 rot2(Euler(0.0, 0.0, getPi<F32>() / 2));
  178. sphereLines->push_back(rot2 * rotPrev);
  179. sphereLines->push_back(rot2 * rotP);
  180. }
  181. prev = p;
  182. }
  183. }
  184. // Render
  185. //
  186. Mat4 oldMMat = mMat;
  187. Mat4 oldVpMat = vpMat;
  188. setModelMatrix(mMat * Mat4(Vec3(0.0), Mat3::getIdentity(), radius));
  189. begin();
  190. for(const Vec3& p : *sphereLines)
  191. {
  192. pushBackVertex(p);
  193. }
  194. end();
  195. // restore
  196. mMat = oldMMat;
  197. vpMat = oldVpMat;
  198. }
  199. //==============================================================================
  200. void DebugDrawer::drawCube(F32 size)
  201. {
  202. Vec3 maxPos = Vec3(0.5 * size);
  203. Vec3 minPos = Vec3(-0.5 * size);
  204. Array<Vec3, 8> points = {{
  205. Vec3(maxPos.x(), maxPos.y(), maxPos.z()), // right top front
  206. Vec3(minPos.x(), maxPos.y(), maxPos.z()), // left top front
  207. Vec3(minPos.x(), minPos.y(), maxPos.z()), // left bottom front
  208. Vec3(maxPos.x(), minPos.y(), maxPos.z()), // right bottom front
  209. Vec3(maxPos.x(), maxPos.y(), minPos.z()), // right top back
  210. Vec3(minPos.x(), maxPos.y(), minPos.z()), // left top back
  211. Vec3(minPos.x(), minPos.y(), minPos.z()), // left bottom back
  212. Vec3(maxPos.x(), minPos.y(), minPos.z()) // right bottom back
  213. }};
  214. static const Array<uint, 24> indeces = {{
  215. 0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6,
  216. 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7}};
  217. begin();
  218. for(uint id : indeces)
  219. {
  220. pushBackVertex(points[id]);
  221. }
  222. end();
  223. }
  224. //==============================================================================
  225. // CollisionDebugDrawer =
  226. //==============================================================================
  227. //==============================================================================
  228. void CollisionDebugDrawer::visit(const Sphere& sphere)
  229. {
  230. dbg->setModelMatrix(Mat4(sphere.getCenter(), Mat3::getIdentity(), 1.0));
  231. dbg->drawSphere(sphere.getRadius());
  232. }
  233. //==============================================================================
  234. void CollisionDebugDrawer::visit(const Obb& obb)
  235. {
  236. Mat4 scale(Mat4::getIdentity());
  237. scale(0, 0) = obb.getExtend().x();
  238. scale(1, 1) = obb.getExtend().y();
  239. scale(2, 2) = obb.getExtend().z();
  240. Mat4 rot(obb.getRotation());
  241. Mat4 trs(obb.getCenter());
  242. Mat4 tsl;
  243. tsl = Mat4::combineTransformations(rot, scale);
  244. tsl = Mat4::combineTransformations(trs, tsl);
  245. dbg->setModelMatrix(tsl);
  246. dbg->setColor(Vec3(1.0, 1.0, 0.0));
  247. dbg->drawCube(2.0);
  248. }
  249. //==============================================================================
  250. void CollisionDebugDrawer::visit(const Plane& plane)
  251. {
  252. const Vec3& n = plane.getNormal();
  253. const F32& o = plane.getOffset();
  254. Quat q;
  255. q.setFrom2Vec3(Vec3(0.0, 0.0, 1.0), n);
  256. Mat3 rot(q);
  257. rot.rotateXAxis(getPi<F32>() / 2.0);
  258. Mat4 trf(n * o, rot);
  259. dbg->setModelMatrix(trf);
  260. dbg->drawGrid();
  261. }
  262. //==============================================================================
  263. void CollisionDebugDrawer::visit(const Aabb& aabb)
  264. {
  265. const Vec3& min = aabb.getMin();
  266. const Vec3& max = aabb.getMax();
  267. Mat4 trf = Mat4::getIdentity();
  268. // Scale
  269. for(uint i = 0; i < 3; ++i)
  270. {
  271. trf(i, i) = max[i] - min[i];
  272. }
  273. // Translation
  274. trf.setTranslationPart((max + min) / 2.0);
  275. dbg->setModelMatrix(trf);
  276. dbg->drawCube();
  277. }
  278. //==============================================================================
  279. void CollisionDebugDrawer::visit(const Frustum& f)
  280. {
  281. switch(f.getFrustumType())
  282. {
  283. case Frustum::FT_ORTHOGRAPHIC:
  284. visit(static_cast<const OrthographicFrustum&>(f).getObb());
  285. break;
  286. case Frustum::FT_PERSPECTIVE:
  287. {
  288. dbg->setColor(Vec4(0.5, 0.0, 0.5, 1.0));
  289. const PerspectiveFrustum& pf =
  290. static_cast<const PerspectiveFrustum&>(f);
  291. F32 camLen = pf.getFar();
  292. F32 tmp0 = camLen / tan((getPi<F32>() - pf.getFovX()) * 0.5)
  293. + 0.001;
  294. F32 tmp1 = camLen * tan(pf.getFovY() * 0.5) + 0.001;
  295. Vec3 points[] = {
  296. Vec3(0.0, 0.0, 0.0), // 0: eye point
  297. Vec3(-tmp0, tmp1, -camLen), // 1: top left
  298. Vec3(-tmp0, -tmp1, -camLen), // 2: bottom left
  299. Vec3(tmp0, -tmp1, -camLen), // 3: bottom right
  300. Vec3(tmp0, tmp1, -camLen) // 4: top right
  301. };
  302. const uint indeces[] = {0, 1, 0, 2, 0, 3, 0, 4, 1, 2, 2,
  303. 3, 3, 4, 4, 1};
  304. dbg->begin();
  305. for(uint i = 0; i < sizeof(indeces) / sizeof(uint); i++)
  306. {
  307. dbg->pushBackVertex(points[indeces[i]]);
  308. }
  309. dbg->end();
  310. break;
  311. }
  312. }
  313. }
  314. //==============================================================================
  315. // PhysicsDebugDrawer =
  316. //==============================================================================
  317. //==============================================================================
  318. void PhysicsDebugDrawer::drawLine(const btVector3& from, const btVector3& to,
  319. const btVector3& color)
  320. {
  321. dbg->drawLine(toAnki(from), toAnki(to), Vec4(toAnki(color), 1.0));
  322. }
  323. //==============================================================================
  324. void PhysicsDebugDrawer::drawSphere(btScalar radius,
  325. const btTransform& transform,
  326. const btVector3& color)
  327. {
  328. dbg->setColor(toAnki(color));
  329. dbg->setModelMatrix(Mat4(toAnki(transform)));
  330. dbg->drawSphere(radius);
  331. }
  332. //==============================================================================
  333. void PhysicsDebugDrawer::drawBox(const btVector3& min, const btVector3& max,
  334. const btVector3& color)
  335. {
  336. Mat4 trf(Mat4::getIdentity());
  337. trf(0, 0) = max.getX() - min.getX();
  338. trf(1, 1) = max.getY() - min.getY();
  339. trf(2, 2) = max.getZ() - min.getZ();
  340. trf(0, 3) = (max.getX() + min.getX()) / 2.0;
  341. trf(1, 3) = (max.getY() + min.getY()) / 2.0;
  342. trf(2, 3) = (max.getZ() + min.getZ()) / 2.0;
  343. dbg->setModelMatrix(trf);
  344. dbg->setColor(toAnki(color));
  345. dbg->drawCube(1.0);
  346. }
  347. //==============================================================================
  348. void PhysicsDebugDrawer::drawBox(const btVector3& min, const btVector3& max,
  349. const btTransform& trans, const btVector3& color)
  350. {
  351. Mat4 trf(Mat4::getIdentity());
  352. trf(0, 0) = max.getX() - min.getX();
  353. trf(1, 1) = max.getY() - min.getY();
  354. trf(2, 2) = max.getZ() - min.getZ();
  355. trf(0, 3) = (max.getX() + min.getX()) / 2.0;
  356. trf(1, 3) = (max.getY() + min.getY()) / 2.0;
  357. trf(2, 3) = (max.getZ() + min.getZ()) / 2.0;
  358. trf = Mat4::combineTransformations(Mat4(toAnki(trans)), trf);
  359. dbg->setModelMatrix(trf);
  360. dbg->setColor(toAnki(color));
  361. dbg->drawCube(1.0);
  362. }
  363. //==============================================================================
  364. void PhysicsDebugDrawer::drawContactPoint(const btVector3& /*pointOnB*/,
  365. const btVector3& /*normalOnB*/,
  366. btScalar /*distance*/, int /*lifeTime*/, const btVector3& /*color*/)
  367. {
  368. //ANKI_LOGW("Unimplemented");
  369. }
  370. //==============================================================================
  371. void PhysicsDebugDrawer::reportErrorWarning(const char* warningString)
  372. {
  373. throw ANKI_EXCEPTION(warningString);
  374. }
  375. //==============================================================================
  376. void PhysicsDebugDrawer::draw3dText(const btVector3& /*location*/,
  377. const char* /*textString*/)
  378. {
  379. //ANKI_LOGW("Unimplemented");
  380. }
  381. //==============================================================================
  382. // SceneDebugDrawer =
  383. //==============================================================================
  384. //==============================================================================
  385. void SceneDebugDrawer::draw(SceneNode& node)
  386. {
  387. // Nothing to render?
  388. if(getFlagsBitmask() == 0)
  389. {
  390. return;
  391. }
  392. Movable* mv = node.getMovable();
  393. if(mv)
  394. {
  395. dbg->setModelMatrix(Mat4(mv->getWorldTransform()));
  396. }
  397. else
  398. {
  399. dbg->setModelMatrix(Mat4::getIdentity());
  400. }
  401. Frustumable* fr;
  402. if(isFlagEnabled(DF_FRUSTUMABLE) && (fr = node.getFrustumable()))
  403. {
  404. draw(*fr);
  405. }
  406. Spatial* sp;
  407. if(isFlagEnabled(DF_SPATIAL) && (sp = node.getSpatial())
  408. && sp->isFlagEnabled(Spatial::SF_VISIBLE_CAMERA))
  409. {
  410. draw(*sp);
  411. }
  412. }
  413. //==============================================================================
  414. void SceneDebugDrawer::draw(Frustumable& fr) const
  415. {
  416. const Frustum& fs = fr.getFrustum();
  417. CollisionDebugDrawer coldraw(dbg);
  418. fs.accept(coldraw);
  419. }
  420. //==============================================================================
  421. void SceneDebugDrawer::draw(Spatial& x) const
  422. {
  423. CollisionDebugDrawer coldraw(dbg);
  424. x.getAabb().accept(coldraw);
  425. }
  426. //==============================================================================
  427. void SceneDebugDrawer::draw(const Octree& octree) const
  428. {
  429. dbg->setColor(Vec3(1.0));
  430. draw(octree.getRoot(), 0, octree);
  431. }
  432. //==============================================================================
  433. void SceneDebugDrawer::draw(const OctreeNode& octnode, U32 depth,
  434. const Octree& octree) const
  435. {
  436. PtrSize nodesCount =
  437. octnode.getSceneNodesEnd() - octnode.getSceneNodesBegin();
  438. // Draw if it has spatials
  439. if(nodesCount != 0)
  440. {
  441. //Vec3 color = Vec3(1.0 - F32(depth) / F32(octree.getMaxDepth()));
  442. Vec3 color(1.0);
  443. dbg->setColor(color);
  444. CollisionDebugDrawer v(dbg);
  445. octnode.getAabb().accept(v);
  446. }
  447. // Children
  448. for(U32 i = 0; i < 8; ++i)
  449. {
  450. if(octnode.getChild(i) != nullptr)
  451. {
  452. draw(*octnode.getChild(i), depth + 1, octree);
  453. }
  454. }
  455. }
  456. //==============================================================================
  457. void SceneDebugDrawer::draw(const Sector& sector)
  458. {
  459. if(!isFlagEnabled(DF_SECTOR))
  460. {
  461. return;
  462. }
  463. // Draw the sector
  464. dbg->setColor(Vec3(0.5, 0.5, 1.0));
  465. CollisionDebugDrawer v(dbg);
  466. sector.getAabb().accept(v);
  467. // Draw the portals
  468. dbg->setColor(Vec3(0.0, 0.0, 1.0));
  469. for(const Portal* portal : sector.getSectorGroup().getPortals())
  470. {
  471. if(portal->sectors[0] == &sector || portal->sectors[1] == &sector)
  472. {
  473. portal->shape.accept(v);
  474. }
  475. }
  476. // Draw the octree
  477. if(isFlagEnabled(DF_OCTREE))
  478. {
  479. draw(sector.getOctree());
  480. }
  481. }
  482. } // end namespace anki