packrect.h 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. /*
  2. * Copyright 2011-2025 Branimir Karadzic. All rights reserved.
  3. * License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE
  4. */
  5. #ifndef RECTPACK_H_HEADER_GUARD
  6. #define RECTPACK_H_HEADER_GUARD
  7. #include <bx/uint32_t.h>
  8. struct Pack2D
  9. {
  10. uint16_t m_x;
  11. uint16_t m_y;
  12. uint16_t m_width;
  13. uint16_t m_height;
  14. };
  15. struct PackCube
  16. {
  17. Pack2D m_rect;
  18. uint8_t m_side;
  19. };
  20. template <uint16_t numBlocks>
  21. class RectPackCubeT;
  22. template <uint16_t numBlocks>
  23. class RectPack2DT
  24. {
  25. public:
  26. RectPack2DT(uint16_t _width, uint16_t _height)
  27. {
  28. reset(_width, _height);
  29. }
  30. void reset(uint16_t _width, uint16_t _height)
  31. {
  32. m_bw = _width/64;
  33. m_bh = _height/numBlocks;
  34. bx::memSet(m_mem, 0xff, sizeof(m_mem) );
  35. }
  36. bool find(uint16_t _width, uint16_t _height, Pack2D& _pack)
  37. {
  38. uint16_t width = bx::min<uint16_t>(64, (_width + m_bw - 1) / m_bw);
  39. uint16_t height = bx::min<uint16_t>(numBlocks, (_height + m_bh - 1) / m_bh);
  40. uint16_t numx = 64-width;
  41. uint16_t numy = numBlocks-height;
  42. const uint64_t scan = width == 64 ? UINT64_MAX : (UINT64_C(1)<<width)-1;
  43. for (uint16_t starty = 0; starty <= numy; ++starty)
  44. {
  45. uint64_t mem = m_mem[starty];
  46. uint16_t ntz = (uint16_t)bx::uint64_cnttz(mem);
  47. uint64_t mask = scan<<ntz;
  48. for (uint16_t xx = ntz; xx <= numx; ++xx, mask <<= 1)
  49. {
  50. uint16_t yy = starty;
  51. if ( (mem&mask) == mask)
  52. {
  53. uint16_t endy = starty + height;
  54. while (yy < endy && (m_mem[yy]&mask) == mask)
  55. {
  56. ++yy;
  57. }
  58. if (yy == endy)
  59. {
  60. uint64_t cmask = ~mask;
  61. for (yy = starty; yy < endy; ++yy)
  62. {
  63. m_mem[yy] &= cmask;
  64. }
  65. _pack.m_x = xx * m_bw;
  66. _pack.m_y = starty * m_bh;
  67. _pack.m_width = width * m_bw;
  68. _pack.m_height = height * m_bh;
  69. return true;
  70. }
  71. }
  72. }
  73. }
  74. return false;
  75. }
  76. void clear(const Pack2D& _pack)
  77. {
  78. uint16_t startx = bx::min<uint16_t>(63, _pack.m_x / m_bw);
  79. uint16_t starty = bx::min<uint16_t>(numBlocks-1, _pack.m_y / m_bh);
  80. uint16_t endx = bx::min<uint16_t>(64, (_pack.m_width + m_bw - 1) / m_bw + startx);
  81. uint16_t endy = bx::min<uint16_t>(numBlocks, (_pack.m_height + m_bh - 1) / m_bh + starty);
  82. uint16_t width = endx - startx;
  83. const uint64_t mask = (width == 64 ? UINT64_MAX : (UINT64_C(1)<<width)-1 )<<startx;
  84. for (uint16_t yy = starty; yy < endy; ++yy)
  85. {
  86. m_mem[yy] |= mask;
  87. }
  88. }
  89. private:
  90. friend class RectPackCubeT<numBlocks>;
  91. RectPack2DT()
  92. {
  93. }
  94. uint64_t m_mem[numBlocks];
  95. uint16_t m_bw;
  96. uint16_t m_bh;
  97. };
  98. template <uint16_t numBlocks>
  99. class RectPackCubeT
  100. {
  101. public:
  102. RectPackCubeT(uint16_t _side)
  103. {
  104. reset(_side);
  105. }
  106. void reset(uint16_t _side)
  107. {
  108. for (uint8_t ii = 0; ii < 6; ++ii)
  109. {
  110. m_mru[ii] = ii;
  111. m_ra[ii].reset(_side, _side);
  112. }
  113. }
  114. bool find(uint16_t _width, uint16_t _height, PackCube& _pack)
  115. {
  116. bool found = false;
  117. for (uint32_t ii = 0; ii < 6; ++ii)
  118. {
  119. uint8_t side = m_mru[ii];
  120. found = m_ra[side].find(_width, _height, _pack.m_rect);
  121. if (found)
  122. {
  123. _pack.m_side = side;
  124. m_mru[ii] = m_mru[0];
  125. m_mru[0] = side;
  126. return true;
  127. }
  128. }
  129. return false;
  130. }
  131. void clear(const PackCube& _pack)
  132. {
  133. uint8_t side = _pack.m_side;
  134. uint32_t ii = 0;
  135. for (; ii < 6 && m_mru[ii] != side; ++ii) {};
  136. m_mru[ii] = m_mru[0];
  137. m_mru[0] = side;
  138. m_ra[side].clear(_pack.m_rect);
  139. }
  140. private:
  141. RectPackCubeT();
  142. RectPack2DT<numBlocks> m_ra[6];
  143. uint8_t m_mru[6];
  144. };
  145. #endif // RECTPACK_H_HEADER_GUARD