cube_atlas.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540
  1. /*
  2. * Copyright 2013 Jeremie Roy. All rights reserved.
  3. * License: http://www.opensource.org/licenses/BSD-2-Clause
  4. */
  5. #include <bx/bx.h>
  6. #include <bgfx.h>
  7. #include <limits.h> // INT_MAX
  8. #include <memory.h> // memset
  9. #include <vector>
  10. #include "cube_atlas.h"
  11. class RectanglePacker
  12. {
  13. public:
  14. RectanglePacker();
  15. RectanglePacker(uint32_t _width, uint32_t _height);
  16. /// non constructor initialization
  17. void init(uint32_t _width, uint32_t _height);
  18. /// find a suitable position for the given rectangle
  19. /// @return true if the rectangle can be added, false otherwise
  20. bool addRectangle(uint16_t _width, uint16_t _height, uint16_t& _outX, uint16_t& _outY);
  21. /// return the used surface in squared unit
  22. uint32_t getUsedSurface()
  23. {
  24. return m_usedSpace;
  25. }
  26. /// return the total available surface in squared unit
  27. uint32_t getTotalSurface()
  28. {
  29. return m_width * m_height;
  30. }
  31. /// return the usage ratio of the available surface [0:1]
  32. float getUsageRatio();
  33. /// reset to initial state
  34. void clear();
  35. private:
  36. int32_t fit(uint32_t _skylineNodeIndex, uint16_t _width, uint16_t _height);
  37. /// Merges all skyline nodes that are at the same level.
  38. void merge();
  39. struct Node
  40. {
  41. Node(int16_t _x, int16_t _y, int16_t _width) : m_x(_x), m_y(_y), m_width(_width)
  42. {
  43. }
  44. /// The starting x-coordinate (leftmost).
  45. int16_t m_x;
  46. /// The y-coordinate of the skyline level line.
  47. int16_t m_y;
  48. /// The line _width. The ending coordinate (inclusive) will be x+width-1.
  49. int32_t m_width; // 32bit to avoid padding
  50. };
  51. /// width (in pixels) of the underlying texture
  52. uint32_t m_width;
  53. /// height (in pixels) of the underlying texture
  54. uint32_t m_height;
  55. /// Surface used in squared pixel
  56. uint32_t m_usedSpace;
  57. /// node of the skyline algorithm
  58. std::vector<Node> m_skyline;
  59. };
  60. RectanglePacker::RectanglePacker() : m_width(0), m_height(0), m_usedSpace(0)
  61. {
  62. }
  63. RectanglePacker::RectanglePacker(uint32_t _width, uint32_t _height) : m_width(_width), m_height(_height), m_usedSpace(0)
  64. {
  65. // We want a one pixel border around the whole atlas to avoid any artefact when
  66. // sampling texture
  67. m_skyline.push_back(Node(1, 1, _width - 2) );
  68. }
  69. void RectanglePacker::init(uint32_t _width, uint32_t _height)
  70. {
  71. BX_CHECK(_width > 2, "_width must be > 2");
  72. BX_CHECK(_height > 2, "_height must be > 2");
  73. m_width = _width;
  74. m_height = _height;
  75. m_usedSpace = 0;
  76. m_skyline.clear();
  77. // We want a one pixel border around the whole atlas to avoid any artifact when
  78. // sampling texture
  79. m_skyline.push_back(Node(1, 1, _width - 2) );
  80. }
  81. bool RectanglePacker::addRectangle(uint16_t _width, uint16_t _height, uint16_t& _outX, uint16_t& _outY)
  82. {
  83. int y, best_height, best_index;
  84. int32_t best_width;
  85. Node* node;
  86. Node* prev;
  87. _outX = 0;
  88. _outY = 0;
  89. uint32_t ii;
  90. best_height = INT_MAX;
  91. best_index = -1;
  92. best_width = INT_MAX;
  93. for (ii = 0; ii < m_skyline.size(); ++ii)
  94. {
  95. y = fit(ii, _width, _height);
  96. if (y >= 0)
  97. {
  98. node = &m_skyline[ii];
  99. if ( ( (y + _height) < best_height)
  100. || ( ( (y + _height) == best_height)
  101. && (node->m_width < best_width) ) )
  102. {
  103. best_height = y + _height;
  104. best_index = ii;
  105. best_width = node->m_width;
  106. _outX = node->m_x;
  107. _outY = y;
  108. }
  109. }
  110. }
  111. if (best_index == -1)
  112. {
  113. return false;
  114. }
  115. Node newNode(_outX, _outY + _height, _width);
  116. m_skyline.insert(m_skyline.begin() + best_index, newNode);
  117. for (ii = best_index + 1; ii < m_skyline.size(); ++ii)
  118. {
  119. node = &m_skyline[ii];
  120. prev = &m_skyline[ii - 1];
  121. if (node->m_x < (prev->m_x + prev->m_width) )
  122. {
  123. int shrink = prev->m_x + prev->m_width - node->m_x;
  124. node->m_x += shrink;
  125. node->m_width -= shrink;
  126. if (node->m_width <= 0)
  127. {
  128. m_skyline.erase(m_skyline.begin() + ii);
  129. --ii;
  130. }
  131. else
  132. {
  133. break;
  134. }
  135. }
  136. else
  137. {
  138. break;
  139. }
  140. }
  141. merge();
  142. m_usedSpace += _width * _height;
  143. return true;
  144. }
  145. float RectanglePacker::getUsageRatio()
  146. {
  147. uint32_t total = m_width * m_height;
  148. if (total > 0)
  149. {
  150. return (float) m_usedSpace / (float) total;
  151. }
  152. else
  153. {
  154. return 0.0f;
  155. }
  156. }
  157. void RectanglePacker::clear()
  158. {
  159. m_skyline.clear();
  160. m_usedSpace = 0;
  161. // We want a one pixel border around the whole atlas to avoid any artefact when
  162. // sampling texture
  163. m_skyline.push_back(Node(1, 1, m_width - 2) );
  164. }
  165. int32_t RectanglePacker::fit(uint32_t _skylineNodeIndex, uint16_t _width, uint16_t _height)
  166. {
  167. int32_t width = _width;
  168. int32_t height = _height;
  169. const Node& baseNode = m_skyline[_skylineNodeIndex];
  170. int32_t x = baseNode.m_x, y;
  171. int32_t _width_left = width;
  172. int32_t i = _skylineNodeIndex;
  173. if ( (x + width) > (int32_t)(m_width - 1) )
  174. {
  175. return -1;
  176. }
  177. y = baseNode.m_y;
  178. while (_width_left > 0)
  179. {
  180. const Node& node = m_skyline[i];
  181. if (node.m_y > y)
  182. {
  183. y = node.m_y;
  184. }
  185. if ( (y + height) > (int32_t)(m_height - 1) )
  186. {
  187. return -1;
  188. }
  189. _width_left -= node.m_width;
  190. ++i;
  191. }
  192. return y;
  193. }
  194. void RectanglePacker::merge()
  195. {
  196. Node* node;
  197. Node* next;
  198. uint32_t ii;
  199. for (ii = 0; ii < m_skyline.size() - 1; ++ii)
  200. {
  201. node = (Node*) &m_skyline[ii];
  202. next = (Node*) &m_skyline[ii + 1];
  203. if (node->m_y == next->m_y)
  204. {
  205. node->m_width += next->m_width;
  206. m_skyline.erase(m_skyline.begin() + ii + 1);
  207. --ii;
  208. }
  209. }
  210. }
  211. struct Atlas::PackedLayer
  212. {
  213. RectanglePacker packer;
  214. AtlasRegion faceRegion;
  215. };
  216. Atlas::Atlas(uint16_t _textureSize, uint16_t _maxRegionsCount)
  217. {
  218. BX_CHECK(_textureSize >= 64
  219. && _textureSize <= 4096, "suspicious texture size");
  220. BX_CHECK(_maxRegionsCount >= 64
  221. && _maxRegionsCount <= 32000, "suspicious _regions count");
  222. m_layers = new PackedLayer[24];
  223. for (int ii = 0; ii < 24; ++ii)
  224. {
  225. m_layers[ii].packer.init(_textureSize, _textureSize);
  226. }
  227. m_usedLayers = 0;
  228. m_usedFaces = 0;
  229. m_textureSize = _textureSize;
  230. m_regionCount = 0;
  231. m_maxRegionCount = _maxRegionsCount;
  232. m_regions = new AtlasRegion[_maxRegionsCount];
  233. m_textureBuffer = new uint8_t[ _textureSize * _textureSize * 6 * 4 ];
  234. memset(m_textureBuffer, 0, _textureSize * _textureSize * 6 * 4);
  235. //BGFX_TEXTURE_MIN_POINT|BGFX_TEXTURE_MAG_POINT|BGFX_TEXTURE_MIP_POINT;
  236. //BGFX_TEXTURE_MIN_ANISOTROPIC|BGFX_TEXTURE_MAG_ANISOTROPIC|BGFX_TEXTURE_MIP_POINT
  237. //BGFX_TEXTURE_U_CLAMP|BGFX_TEXTURE_V_CLAMP
  238. uint32_t flags = 0; // BGFX_TEXTURE_MIN_ANISOTROPIC|BGFX_TEXTURE_MAG_ANISOTROPIC|BGFX_TEXTURE_MIP_POINT;
  239. //Uncomment this to debug atlas
  240. //const bgfx::Memory* mem = bgfx::alloc(textureSize*textureSize * 6 * 4);
  241. //memset(mem->data, 255, mem->size);
  242. const bgfx::Memory* mem = NULL;
  243. m_textureHandle = bgfx::createTextureCube(6
  244. , _textureSize
  245. , 1
  246. , bgfx::TextureFormat::BGRA8
  247. , flags
  248. , mem
  249. );
  250. }
  251. Atlas::Atlas(uint16_t _textureSize, const uint8_t* _textureBuffer, uint16_t _regionCount, const uint8_t* _regionBuffer, uint16_t _maxRegionsCount)
  252. {
  253. BX_CHECK(_regionCount <= 64
  254. && _maxRegionsCount <= 4096, "suspicious initialization");
  255. //layers are frozen
  256. m_usedLayers = 24;
  257. m_usedFaces = 6;
  258. m_textureSize = _textureSize;
  259. m_regionCount = _regionCount;
  260. //regions are frozen
  261. if (_regionCount < _maxRegionsCount)
  262. {
  263. m_maxRegionCount = _regionCount;
  264. }
  265. else
  266. {
  267. m_maxRegionCount = _maxRegionsCount;
  268. }
  269. m_regions = new AtlasRegion[_regionCount];
  270. m_textureBuffer = new uint8_t[getTextureBufferSize()];
  271. //BGFX_TEXTURE_MIN_POINT|BGFX_TEXTURE_MAG_POINT|BGFX_TEXTURE_MIP_POINT;
  272. //BGFX_TEXTURE_MIN_ANISOTROPIC|BGFX_TEXTURE_MAG_ANISOTROPIC|BGFX_TEXTURE_MIP_POINT
  273. //BGFX_TEXTURE_U_CLAMP|BGFX_TEXTURE_V_CLAMP
  274. uint32_t flags = 0; //BGFX_TEXTURE_MIN_ANISOTROPIC|BGFX_TEXTURE_MAG_ANISOTROPIC|BGFX_TEXTURE_MIP_POINT;
  275. memcpy(m_regions, _regionBuffer, _regionCount * sizeof(AtlasRegion) );
  276. memcpy(m_textureBuffer, _textureBuffer, getTextureBufferSize() );
  277. m_textureHandle = bgfx::createTextureCube(6
  278. , _textureSize
  279. , 1
  280. , bgfx::TextureFormat::BGRA8
  281. , flags
  282. , bgfx::makeRef(m_textureBuffer, getTextureBufferSize() )
  283. );
  284. }
  285. Atlas::~Atlas()
  286. {
  287. delete[] m_layers;
  288. delete[] m_regions;
  289. delete[] m_textureBuffer;
  290. }
  291. uint16_t Atlas::addRegion(uint16_t _width, uint16_t _height, const uint8_t* _bitmapBuffer, AtlasRegion::Type _type, uint16_t outline)
  292. {
  293. if (m_regionCount >= m_maxRegionCount)
  294. {
  295. return UINT16_MAX;
  296. }
  297. uint16_t x = 0, y = 0;
  298. // We want each bitmap to be separated by at least one black pixel
  299. // TODO manage mipmaps
  300. uint32_t idx = 0;
  301. while (idx < m_usedLayers)
  302. {
  303. if (m_layers[idx].faceRegion.getType() == _type)
  304. {
  305. if (m_layers[idx].packer.addRectangle(_width + 1, _height + 1, x, y) )
  306. {
  307. break;
  308. }
  309. }
  310. idx++;
  311. }
  312. if (idx >= m_usedLayers)
  313. {
  314. //do we have still room to add layers ?
  315. if ( (idx + _type) > 24
  316. || m_usedFaces >= 6)
  317. {
  318. return UINT16_MAX;
  319. }
  320. //create new layers
  321. for (int ii = 0; ii < _type; ++ii)
  322. {
  323. m_layers[idx + ii].faceRegion.m_x = 0;
  324. m_layers[idx + ii].faceRegion.m_y = 0;
  325. m_layers[idx + ii].faceRegion.m_width = m_textureSize;
  326. m_layers[idx + ii].faceRegion.m_height = m_textureSize;
  327. m_layers[idx + ii].faceRegion.setMask(_type, m_usedFaces, ii);
  328. }
  329. m_usedLayers += _type;
  330. m_usedFaces++;
  331. //add it to the created layer
  332. if (!m_layers[idx].packer.addRectangle(_width + 1, _height + 1, x, y) )
  333. {
  334. return UINT16_MAX;
  335. }
  336. }
  337. AtlasRegion& region = m_regions[m_regionCount];
  338. region.m_x = x;
  339. region.m_y = y;
  340. region.m_width = _width;
  341. region.m_height = _height;
  342. region.m_mask = m_layers[idx].faceRegion.m_mask;
  343. updateRegion(region, _bitmapBuffer);
  344. region.m_x += outline;
  345. region.m_y += outline;
  346. region.m_width -= (outline * 2);
  347. region.m_height -= (outline * 2);
  348. return m_regionCount++;
  349. }
  350. void Atlas::updateRegion(const AtlasRegion& _region, const uint8_t* _bitmapBuffer)
  351. {
  352. const bgfx::Memory* mem = bgfx::alloc(_region.m_width * _region.m_height * 4);
  353. //BAD!
  354. memset(mem->data, 0, mem->size);
  355. if (_region.getType() == AtlasRegion::TYPE_BGRA8)
  356. {
  357. const uint8_t* inLineBuffer = _bitmapBuffer;
  358. uint8_t* outLineBuffer = m_textureBuffer + _region.getFaceIndex() * (m_textureSize * m_textureSize * 4) + ( ( (_region.m_y * m_textureSize) + _region.m_x) * 4);
  359. //update the cpu buffer
  360. for (int yy = 0; yy < _region.m_height; ++yy)
  361. {
  362. memcpy(outLineBuffer, inLineBuffer, _region.m_width * 4);
  363. inLineBuffer += _region.m_width * 4;
  364. outLineBuffer += m_textureSize * 4;
  365. }
  366. //update the GPU buffer
  367. memcpy(mem->data, _bitmapBuffer, mem->size);
  368. }
  369. else
  370. {
  371. uint32_t layer = _region.getComponentIndex();
  372. //uint32_t face = _region.getFaceIndex();
  373. const uint8_t* inLineBuffer = _bitmapBuffer;
  374. uint8_t* outLineBuffer = (m_textureBuffer + _region.getFaceIndex() * (m_textureSize * m_textureSize * 4) + ( ( (_region.m_y * m_textureSize) + _region.m_x) * 4) );
  375. //update the cpu buffer
  376. for (int yy = 0; yy < _region.m_height; ++yy)
  377. {
  378. for (int xx = 0; xx < _region.m_width; ++xx)
  379. {
  380. outLineBuffer[(xx * 4) + layer] = inLineBuffer[xx];
  381. }
  382. //update the GPU buffer
  383. memcpy(mem->data + yy * _region.m_width * 4, outLineBuffer, _region.m_width * 4);
  384. inLineBuffer += _region.m_width;
  385. outLineBuffer += m_textureSize * 4;
  386. }
  387. }
  388. bgfx::updateTextureCube(m_textureHandle, (uint8_t)_region.getFaceIndex(), 0, _region.m_x, _region.m_y, _region.m_width, _region.m_height, mem);
  389. }
  390. void Atlas::packFaceLayerUV(uint32_t _idx, uint8_t* _vertexBuffer, uint32_t _offset, uint32_t _stride)
  391. {
  392. packUV(m_layers[_idx].faceRegion, _vertexBuffer, _offset, _stride);
  393. }
  394. void Atlas::packUV(uint16_t handle, uint8_t* _vertexBuffer, uint32_t _offset, uint32_t _stride)
  395. {
  396. const AtlasRegion& region = m_regions[handle];
  397. packUV(region, _vertexBuffer, _offset, _stride);
  398. }
  399. void Atlas::packUV(const AtlasRegion& _region, uint8_t* _vertexBuffer, uint32_t _offset, uint32_t _stride)
  400. {
  401. float texMult = 65535.0f / ( (float)(m_textureSize) );
  402. static const int16_t minVal = -32768;
  403. static const int16_t maxVal = 32767;
  404. int16_t x0 = (int16_t)(_region.m_x * texMult) - 32767;
  405. int16_t y0 = (int16_t)(_region.m_y * texMult) - 32767;
  406. int16_t x1 = (int16_t)( (_region.m_x + _region.m_width) * texMult) - 32767;
  407. int16_t y1 = (int16_t)( (_region.m_y + _region.m_height) * texMult) - 32767;
  408. int16_t w = (int16_t) ( (32767.0f / 4.0f) * _region.getComponentIndex() );
  409. _vertexBuffer += _offset;
  410. switch (_region.getFaceIndex() )
  411. {
  412. case 0: // +X
  413. x0 = -x0;
  414. x1 = -x1;
  415. y0 = -y0;
  416. y1 = -y1;
  417. writeUV(_vertexBuffer, maxVal, y0, x0, w); _vertexBuffer += _stride;
  418. writeUV(_vertexBuffer, maxVal, y1, x0, w); _vertexBuffer += _stride;
  419. writeUV(_vertexBuffer, maxVal, y1, x1, w); _vertexBuffer += _stride;
  420. writeUV(_vertexBuffer, maxVal, y0, x1, w); _vertexBuffer += _stride;
  421. break;
  422. case 1: // -X
  423. y0 = -y0;
  424. y1 = -y1;
  425. writeUV(_vertexBuffer, minVal, y0, x0, w); _vertexBuffer += _stride;
  426. writeUV(_vertexBuffer, minVal, y1, x0, w); _vertexBuffer += _stride;
  427. writeUV(_vertexBuffer, minVal, y1, x1, w); _vertexBuffer += _stride;
  428. writeUV(_vertexBuffer, minVal, y0, x1, w); _vertexBuffer += _stride;
  429. break;
  430. case 2: // +Y
  431. writeUV(_vertexBuffer, x0, maxVal, y0, w); _vertexBuffer += _stride;
  432. writeUV(_vertexBuffer, x0, maxVal, y1, w); _vertexBuffer += _stride;
  433. writeUV(_vertexBuffer, x1, maxVal, y1, w); _vertexBuffer += _stride;
  434. writeUV(_vertexBuffer, x1, maxVal, y0, w); _vertexBuffer += _stride;
  435. break;
  436. case 3: // -Y
  437. y0 = -y0;
  438. y1 = -y1;
  439. writeUV(_vertexBuffer, x0, minVal, y0, w); _vertexBuffer += _stride;
  440. writeUV(_vertexBuffer, x0, minVal, y1, w); _vertexBuffer += _stride;
  441. writeUV(_vertexBuffer, x1, minVal, y1, w); _vertexBuffer += _stride;
  442. writeUV(_vertexBuffer, x1, minVal, y0, w); _vertexBuffer += _stride;
  443. break;
  444. case 4: // +Z
  445. y0 = -y0;
  446. y1 = -y1;
  447. writeUV(_vertexBuffer, x0, y0, maxVal, w); _vertexBuffer += _stride;
  448. writeUV(_vertexBuffer, x0, y1, maxVal, w); _vertexBuffer += _stride;
  449. writeUV(_vertexBuffer, x1, y1, maxVal, w); _vertexBuffer += _stride;
  450. writeUV(_vertexBuffer, x1, y0, maxVal, w); _vertexBuffer += _stride;
  451. break;
  452. case 5: // -Z
  453. x0 = -x0;
  454. x1 = -x1;
  455. y0 = -y0;
  456. y1 = -y1;
  457. writeUV(_vertexBuffer, x0, y0, minVal, w); _vertexBuffer += _stride;
  458. writeUV(_vertexBuffer, x0, y1, minVal, w); _vertexBuffer += _stride;
  459. writeUV(_vertexBuffer, x1, y1, minVal, w); _vertexBuffer += _stride;
  460. writeUV(_vertexBuffer, x1, y0, minVal, w); _vertexBuffer += _stride;
  461. break;
  462. }
  463. }