imgui.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441
  1. /*
  2. * Copyright 2011-2017 Branimir Karadzic. All rights reserved.
  3. * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
  4. */
  5. #include <bx/string.h>
  6. #include <bx/uint32_t.h>
  7. #include <bx/fpumath.h>
  8. #include <bx/handlealloc.h>
  9. #include <bx/crtimpl.h>
  10. #include "imgui.h"
  11. #include "ocornut_imgui.h"
  12. #include "../bgfx_utils.h"
  13. #include "../nanovg/nanovg.h"
  14. BX_PRAGMA_DIAGNOSTIC_IGNORED_MSVC(4244); // warning C4244: '=' : conversion from '' to '', possible loss of data
  15. void* imguiMalloc(size_t _size, void*);
  16. void imguiFree(void* _ptr, void*);
  17. BX_PRAGMA_DIAGNOSTIC_IGNORED_MSVC(4505); // error C4505: '' : unreferenced local function has been removed
  18. BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG_GCC("-Wunused-function"); // warning: ‘int rect_width_compare(const void*, const void*)’ defined but not used
  19. BX_PRAGMA_DIAGNOSTIC_PUSH();
  20. BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG("-Wunknown-pragmas")
  21. BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG_GCC("-Wunused-but-set-variable"); // warning: variable ‘L1’ set but not used
  22. BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG_GCC("-Wtype-limits"); // warning: comparison is always true due to limited range of data type
  23. #define STBTT_malloc(_size, _userData) imguiMalloc(_size, _userData)
  24. #define STBTT_free(_ptr, _userData) imguiFree(_ptr, _userData)
  25. #define STB_RECT_PACK_IMPLEMENTATION
  26. #include <stb/stb_rect_pack.h>
  27. #define STB_TRUETYPE_IMPLEMENTATION
  28. #include <stb/stb_truetype.h>
  29. BX_PRAGMA_DIAGNOSTIC_POP();
  30. namespace
  31. {
  32. static uint32_t addQuad(uint16_t* _indices, uint16_t _idx0, uint16_t _idx1, uint16_t _idx2, uint16_t _idx3)
  33. {
  34. _indices[0] = _idx0;
  35. _indices[1] = _idx3;
  36. _indices[2] = _idx1;
  37. _indices[3] = _idx1;
  38. _indices[4] = _idx3;
  39. _indices[5] = _idx2;
  40. return 6;
  41. }
  42. float sign(float px, float py, float ax, float ay, float bx, float by)
  43. {
  44. return (px - bx) * (ay - by) - (ax - bx) * (py - by);
  45. }
  46. bool pointInTriangle(float px, float py, float ax, float ay, float bx, float by, float cx, float cy)
  47. {
  48. const bool b1 = sign(px, py, ax, ay, bx, by) < 0.0f;
  49. const bool b2 = sign(px, py, bx, by, cx, cy) < 0.0f;
  50. const bool b3 = sign(px, py, cx, cy, ax, ay) < 0.0f;
  51. return ( (b1 == b2) && (b2 == b3) );
  52. }
  53. void closestPointOnLine(float& ox, float &oy, float px, float py, float ax, float ay, float bx, float by)
  54. {
  55. float dx = px - ax;
  56. float dy = py - ay;
  57. float lx = bx - ax;
  58. float ly = by - ay;
  59. float len = bx::fsqrt(lx*lx+ly*ly);
  60. // Normalize.
  61. float invLen = 1.0f/len;
  62. lx*=invLen;
  63. ly*=invLen;
  64. float dot = (dx*lx + dy*ly);
  65. if (dot < 0.0f)
  66. {
  67. ox = ax;
  68. oy = ay;
  69. }
  70. else if (dot > len)
  71. {
  72. ox = bx;
  73. oy = by;
  74. }
  75. else
  76. {
  77. ox = ax + lx*dot;
  78. oy = ay + ly*dot;
  79. }
  80. }
  81. void closestPointOnTriangle(float& ox, float &oy, float px, float py, float ax, float ay, float bx, float by, float cx, float cy)
  82. {
  83. float abx, aby;
  84. float bcx, bcy;
  85. float cax, cay;
  86. closestPointOnLine(abx, aby, px, py, ax, ay, bx, by);
  87. closestPointOnLine(bcx, bcy, px, py, bx, by, cx, cy);
  88. closestPointOnLine(cax, cay, px, py, cx, cy, ax, ay);
  89. const float pabx = px - abx;
  90. const float paby = py - aby;
  91. const float pbcx = px - bcx;
  92. const float pbcy = py - bcy;
  93. const float pcax = px - cax;
  94. const float pcay = py - cay;
  95. const float lab = bx::fsqrt(pabx*pabx+paby*paby);
  96. const float lbc = bx::fsqrt(pbcx*pbcx+pbcy*pbcy);
  97. const float lca = bx::fsqrt(pcax*pcax+pcay*pcay);
  98. const float m = bx::fmin3(lab, lbc, lca);
  99. if (m == lab)
  100. {
  101. ox = abx;
  102. oy = aby;
  103. }
  104. else if (m == lbc)
  105. {
  106. ox = bcx;
  107. oy = bcy;
  108. }
  109. else// if (m == lca).
  110. {
  111. ox = cax;
  112. oy = cay;
  113. }
  114. }
  115. inline float vec2Dot(const float* __restrict _a, const float* __restrict _b)
  116. {
  117. return _a[0]*_b[0] + _a[1]*_b[1];
  118. }
  119. void barycentric(float& _u, float& _v, float& _w
  120. , float _ax, float _ay
  121. , float _bx, float _by
  122. , float _cx, float _cy
  123. , float _px, float _py
  124. )
  125. {
  126. const float v0[2] = { _bx - _ax, _by - _ay };
  127. const float v1[2] = { _cx - _ax, _cy - _ay };
  128. const float v2[2] = { _px - _ax, _py - _ay };
  129. const float d00 = vec2Dot(v0, v0);
  130. const float d01 = vec2Dot(v0, v1);
  131. const float d11 = vec2Dot(v1, v1);
  132. const float d20 = vec2Dot(v2, v0);
  133. const float d21 = vec2Dot(v2, v1);
  134. const float denom = d00 * d11 - d01 * d01;
  135. _v = (d11 * d20 - d01 * d21) / denom;
  136. _w = (d00 * d21 - d01 * d20) / denom;
  137. _u = 1.0f - _v - _w;
  138. }
  139. } // namespace
  140. bgfx::TextureHandle genMissingTexture(uint32_t _width, uint32_t _height, float _lineWidth = 0.02f)
  141. {
  142. const bgfx::Memory* mem = bgfx::alloc(_width*_height*4);
  143. uint32_t* bgra8 = (uint32_t*)mem->data;
  144. const float sx = 0.70710677f;
  145. const float cx = 0.70710677f;
  146. for (uint32_t yy = 0; yy < _height; ++yy)
  147. {
  148. for (uint32_t xx = 0; xx < _width; ++xx)
  149. {
  150. float px = xx / float(_width) * 2.0f - 1.0f;
  151. float py = yy / float(_height) * 2.0f - 1.0f;
  152. float sum = bx::fpulse(px * cx - py * sx, _lineWidth, -_lineWidth)
  153. + bx::fpulse(px * sx + py * cx, _lineWidth, -_lineWidth)
  154. ;
  155. *bgra8++ = sum >= 1.0f ? 0xffff0000 : 0xffffffff;
  156. }
  157. }
  158. return bgfx::createTexture2D(
  159. uint16_t(_width)
  160. , uint16_t(_height)
  161. , false
  162. , 1
  163. , bgfx::TextureFormat::BGRA8
  164. , 0
  165. , mem
  166. );
  167. }
  168. struct Imgui
  169. {
  170. Imgui()
  171. : m_mx(-1)
  172. , m_my(-1)
  173. , m_scroll(0)
  174. , m_textureWidth(512)
  175. , m_textureHeight(512)
  176. , m_halfTexel(0.0f)
  177. , m_view(255)
  178. , m_surfaceWidth(0)
  179. , m_surfaceHeight(0)
  180. , m_viewWidth(0)
  181. , m_viewHeight(0)
  182. {
  183. m_invTextureWidth = 1.0f/m_textureWidth;
  184. m_invTextureHeight = 1.0f/m_textureHeight;
  185. }
  186. void beginFrame(int32_t _mx, int32_t _my, uint8_t _button, int32_t _scroll, uint16_t _width, uint16_t _height, uint16_t _surfaceWidth, uint16_t _surfaceHeight, char _inputChar, uint8_t _view)
  187. {
  188. m_view = _view;
  189. m_viewWidth = _width;
  190. m_viewHeight = _height;
  191. m_surfaceWidth = _surfaceWidth;
  192. m_surfaceHeight = _surfaceHeight;
  193. const float xscale = float(m_surfaceWidth) /float(m_viewWidth);
  194. const float yscale = float(m_surfaceHeight)/float(m_viewHeight);
  195. const int32_t mx = int32_t(float(_mx)*xscale);
  196. const int32_t my = int32_t(float(_my)*yscale);
  197. IMGUI_beginFrame(mx, my, _button, _scroll, _width, _height, _inputChar, _view);
  198. bgfx::setViewName(_view, "ImGui");
  199. bgfx::setViewMode(_view, bgfx::ViewMode::Sequential);
  200. const bgfx::HMD* hmd = bgfx::getHMD();
  201. const bgfx::Caps* caps = bgfx::getCaps();
  202. if (NULL != hmd && 0 != (hmd->flags & BGFX_HMD_RENDERING) )
  203. {
  204. m_viewWidth = _width / 2;
  205. m_surfaceWidth = _surfaceWidth / 2;
  206. float proj[16];
  207. bx::mtxProj(proj, hmd->eye[0].fov, 0.1f, 100.0f, bgfx::getCaps()->homogeneousDepth);
  208. static float time = 0.0f;
  209. time += 0.05f;
  210. const float dist = 10.0f;
  211. const float offset0 = -proj[8] + (hmd->eye[0].viewOffset[0] / dist * proj[0]);
  212. const float offset1 = -proj[8] + (hmd->eye[1].viewOffset[0] / dist * proj[0]);
  213. float ortho[2][16];
  214. const float viewOffset = _surfaceWidth/4.0f;
  215. const float viewWidth = _surfaceWidth/2.0f;
  216. bx::mtxOrtho(ortho[0], viewOffset, viewOffset + viewWidth, (float)m_surfaceHeight, 0.0f, 0.0f, 1000.0f, offset0, caps->homogeneousDepth);
  217. bx::mtxOrtho(ortho[1], viewOffset, viewOffset + viewWidth, (float)m_surfaceHeight, 0.0f, 0.0f, 1000.0f, offset1, caps->homogeneousDepth);
  218. bgfx::setViewTransform(_view, NULL, ortho[0], BGFX_VIEW_STEREO, ortho[1]);
  219. bgfx::setViewRect(_view, 0, 0, hmd->width, hmd->height);
  220. }
  221. else
  222. {
  223. float ortho[16];
  224. bx::mtxOrtho(ortho, 0.0f, (float)m_surfaceWidth, (float)m_surfaceHeight, 0.0f, 0.0f, 1000.0f, 0.0f, caps->homogeneousDepth);
  225. bgfx::setViewTransform(_view, NULL, ortho);
  226. bgfx::setViewRect(_view, 0, 0, _width, _height);
  227. }
  228. }
  229. void endFrame()
  230. {
  231. IMGUI_endFrame();
  232. }
  233. #if 0
  234. bool cubeMap(bgfx::TextureHandle _cubemap, float _lod, bool _cross, bool _sameHeight, ImguiAlign::Enum _align, bool _enabled)
  235. {
  236. const uint32_t id = getId();
  237. Area& area = getCurrentArea();
  238. int32_t xx;
  239. int32_t width;
  240. if (ImguiAlign::Left == _align)
  241. {
  242. xx = area.m_contentX + SCROLL_AREA_PADDING;
  243. width = area.m_widgetW;
  244. }
  245. else if (ImguiAlign::LeftIndented == _align
  246. || ImguiAlign::Right == _align)
  247. {
  248. xx = area.m_widgetX;
  249. width = area.m_widgetW;
  250. }
  251. else //if (ImguiAlign::Center == _align
  252. //|| ImguiAlign::CenterIndented == _align).
  253. {
  254. xx = area.m_widgetX;
  255. width = area.m_widgetW - (area.m_widgetX-area.m_contentX);
  256. }
  257. const bool adjustHeight = (_cross && _sameHeight);
  258. const bool fullHeight = (_cross && !_sameHeight);
  259. if (adjustHeight)
  260. {
  261. xx += width/6;
  262. }
  263. const int32_t height = fullHeight ? (width*3)/4 : (width/2);
  264. const int32_t yy = area.m_widgetY;
  265. area.m_widgetY += height + DEFAULT_SPACING;
  266. const uint32_t numVertices = 14;
  267. const uint32_t numIndices = 36;
  268. if (checkAvailTransientBuffers(numVertices, PosNormalVertex::ms_decl, numIndices) )
  269. {
  270. bgfx::TransientVertexBuffer tvb;
  271. bgfx::allocTransientVertexBuffer(&tvb, numVertices, PosNormalVertex::ms_decl);
  272. bgfx::TransientIndexBuffer tib;
  273. bgfx::allocTransientIndexBuffer(&tib, numIndices);
  274. PosNormalVertex* vertex = (PosNormalVertex*)tvb.data;
  275. uint16_t* indices = (uint16_t*)tib.data;
  276. if (_cross)
  277. {
  278. vertex->set(0.0f, 0.5f, 0.0f, -1.0f, 1.0f, -1.0f); ++vertex;
  279. vertex->set(0.0f, 1.0f, 0.0f, -1.0f, -1.0f, -1.0f); ++vertex;
  280. vertex->set(0.5f, 0.0f, 0.0f, -1.0f, 1.0f, -1.0f); ++vertex;
  281. vertex->set(0.5f, 0.5f, 0.0f, -1.0f, 1.0f, 1.0f); ++vertex;
  282. vertex->set(0.5f, 1.0f, 0.0f, -1.0f, -1.0f, 1.0f); ++vertex;
  283. vertex->set(0.5f, 1.5f, 0.0f, -1.0f, -1.0f, -1.0f); ++vertex;
  284. vertex->set(1.0f, 0.0f, 0.0f, 1.0f, 1.0f, -1.0f); ++vertex;
  285. vertex->set(1.0f, 0.5f, 0.0f, 1.0f, 1.0f, 1.0f); ++vertex;
  286. vertex->set(1.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f); ++vertex;
  287. vertex->set(1.0f, 1.5f, 0.0f, 1.0f, -1.0f, -1.0f); ++vertex;
  288. vertex->set(1.5f, 0.5f, 0.0f, 1.0f, 1.0f, -1.0f); ++vertex;
  289. vertex->set(1.5f, 1.0f, 0.0f, 1.0f, -1.0f, -1.0f); ++vertex;
  290. vertex->set(2.0f, 0.5f, 0.0f, -1.0f, 1.0f, -1.0f); ++vertex;
  291. vertex->set(2.0f, 1.0f, 0.0f, -1.0f, -1.0f, -1.0f); ++vertex;
  292. indices += addQuad(indices, 0, 3, 4, 1);
  293. indices += addQuad(indices, 2, 6, 7, 3);
  294. indices += addQuad(indices, 3, 7, 8, 4);
  295. indices += addQuad(indices, 4, 8, 9, 5);
  296. indices += addQuad(indices, 7, 10, 11, 8);
  297. indices += addQuad(indices, 10, 12, 13, 11);
  298. }
  299. else
  300. {
  301. vertex->set(0.0f, 0.25f, 0.0f, -1.0f, 1.0f, -1.0f); ++vertex;
  302. vertex->set(0.0f, 0.75f, 0.0f, -1.0f, -1.0f, -1.0f); ++vertex;
  303. vertex->set(0.5f, 0.00f, 0.0f, -1.0f, 1.0f, 1.0f); ++vertex;
  304. vertex->set(0.5f, 0.50f, 0.0f, -1.0f, -1.0f, 1.0f); ++vertex;
  305. vertex->set(0.5f, 1.00f, 0.0f, 1.0f, -1.0f, -1.0f); ++vertex;
  306. vertex->set(1.0f, 0.25f, 0.0f, 1.0f, 1.0f, 1.0f); ++vertex;
  307. vertex->set(1.0f, 0.75f, 0.0f, 1.0f, -1.0f, 1.0f); ++vertex;
  308. vertex->set(1.0f, 0.25f, 0.0f, 1.0f, 1.0f, 1.0f); ++vertex;
  309. vertex->set(1.0f, 0.75f, 0.0f, 1.0f, -1.0f, 1.0f); ++vertex;
  310. vertex->set(1.5f, 0.00f, 0.0f, -1.0f, 1.0f, 1.0f); ++vertex;
  311. vertex->set(1.5f, 0.50f, 0.0f, 1.0f, 1.0f, -1.0f); ++vertex;
  312. vertex->set(1.5f, 1.00f, 0.0f, 1.0f, -1.0f, -1.0f); ++vertex;
  313. vertex->set(2.0f, 0.25f, 0.0f, -1.0f, 1.0f, -1.0f); ++vertex;
  314. vertex->set(2.0f, 0.75f, 0.0f, -1.0f, -1.0f, -1.0f); ++vertex;
  315. indices += addQuad(indices, 0, 2, 3, 1);
  316. indices += addQuad(indices, 1, 3, 6, 4);
  317. indices += addQuad(indices, 2, 5, 6, 3);
  318. indices += addQuad(indices, 7, 9, 12, 10);
  319. indices += addQuad(indices, 7, 10, 11, 8);
  320. indices += addQuad(indices, 10, 12, 13, 11);
  321. }
  322. const bool enabled = _enabled && isEnabled(m_areaId);
  323. const bool over = enabled && inRect(xx, yy, width, height);
  324. const bool res = buttonLogic(id, over);
  325. const float widthf = float(width);
  326. const float scale = adjustHeight ? (widthf+0.5f)/3.0f : (widthf*0.5f + 0.25f);
  327. float mtx[16];
  328. bx::mtxSRT(mtx, scale, scale, 1.0f, 0.0f, 0.0f, 0.0f, float(xx), float(yy), 0.0f);
  329. const float lodEnabled[4] = { _lod, float(enabled), 0.0f, 0.0f };
  330. bgfx::setUniform(u_imageLodEnabled, lodEnabled);
  331. bgfx::setTransform(mtx);
  332. bgfx::setTexture(0, s_texColor, _cubemap);
  333. bgfx::setVertexBuffer(0, &tvb);
  334. bgfx::setIndexBuffer(&tib);
  335. bgfx::setState(BGFX_STATE_RGB_WRITE
  336. |BGFX_STATE_ALPHA_WRITE
  337. |BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA)
  338. );
  339. setCurrentScissor();
  340. bgfx::submit(m_view, m_cubeMapProgram);
  341. return res;
  342. }
  343. return false;
  344. }
  345. #endif // 0
  346. int32_t m_mx;
  347. int32_t m_my;
  348. int32_t m_scroll;
  349. uint16_t m_textureWidth;
  350. uint16_t m_textureHeight;
  351. float m_invTextureWidth;
  352. float m_invTextureHeight;
  353. float m_halfTexel;
  354. uint8_t m_view;
  355. uint16_t m_surfaceWidth;
  356. uint16_t m_surfaceHeight;
  357. uint16_t m_viewWidth;
  358. uint16_t m_viewHeight;
  359. };
  360. static Imgui s_imgui;
  361. void imguiBeginFrame(int32_t _mx, int32_t _my, uint8_t _button, int32_t _scroll, uint16_t _width, uint16_t _height, char _inputChar, uint8_t _view)
  362. {
  363. s_imgui.beginFrame(_mx, _my, _button, _scroll, _width, _height, _width, _height, _inputChar, _view);
  364. }
  365. void imguiEndFrame()
  366. {
  367. s_imgui.endFrame();
  368. }