BsTextureAtlasLayout.h 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #pragma once
  4. #include "Prerequisites/BsPrerequisitesUtil.h"
  5. #include "Math/BsVector2.h"
  6. namespace bs
  7. {
  8. /** @addtogroup Image
  9. * @{
  10. */
  11. /** Organizes a set of textures into a single larger texture (an atlas) by minimizing empty space. */
  12. class BS_UTILITY_EXPORT TextureAtlasLayout
  13. {
  14. /** Represent a single node in the texture atlas binary tree. */
  15. class TexAtlasNode
  16. {
  17. public:
  18. TexAtlasNode();
  19. TexAtlasNode(UINT32 x, UINT32 y, UINT32 width, UINT32 height);
  20. UINT32 x, y, width, height;
  21. UINT32 children[2];
  22. bool nodeFull;
  23. };
  24. public:
  25. TextureAtlasLayout();
  26. /**
  27. * Constructs a new texture atlas layout with the provided parameters.
  28. *
  29. * @param[in] width Initial width of the atlas texture.
  30. * @param[in] height Initial height of the atlas texture.
  31. * @param[in] maxWidth Maximum width the atlas texture is allowed to grow to, when elements don't fit.
  32. * @param[in] maxHeight Maximum height the atlas texture is allowed to grow to, when elements don't fit.
  33. * @param[in] pow2 When true the resulting atlas size will always be a power of two.
  34. */
  35. TextureAtlasLayout(UINT32 width, UINT32 height, UINT32 maxWidth, UINT32 maxHeight, bool pow2 = false);
  36. /**
  37. * Attempts to add a new element in the layout. Elements should be added to the atlas from largest to smallest,
  38. * otherwise a non-optimal layout is likely to be generated.
  39. *
  40. * @param[in] width Width of the new element, in pixels.
  41. * @param[in] height Height of the new element, in pixels.
  42. * @param[out] x Horizontal position of the new element within the atlas. Only valid if method returns true.
  43. * @param[out] y Vertical position of the new element within the atlas. Only valid if method returns true.
  44. * @return True if the element was added to the atlas, false if the element doesn't fit.
  45. */
  46. bool addElement(UINT32 width, UINT32 height, UINT32& x, UINT32& y);
  47. /** Removes all entries from the layout. */
  48. void clear();
  49. /** Checks have any elements been added to the layout. */
  50. bool isEmpty() const { return mNodes.size() == 1; }
  51. /** Returns the width of the atlas texture, in pixels. */
  52. UINT32 getWidth() const { return mWidth; }
  53. /** Returns the height of the atlas texture, in pixels. */
  54. UINT32 getHeight() const { return mHeight; }
  55. private:
  56. /*
  57. * Attempts to add a new element to the specified layout node.
  58. *
  59. * @param[in] nodeIdx Index of the node to which to add the element.
  60. * @param[in] width Width of the new element, in pixels.
  61. * @param[in] height Height of the new element, in pixels.
  62. * @param[out] x Horizontal position of the new element within the atlas. Only valid if method
  63. * returns true.
  64. * @param[out] y Vertical position of the new element within the atlas. Only valid if method returns
  65. * true.
  66. * @param[in] allowGrowth When true, the width/height of the atlas will be allowed to grow to fit the element.
  67. * @return True if the element was added to the atlas, false if the element doesn't fit.
  68. */
  69. bool addToNode(UINT32 nodeIdx, UINT32 width, UINT32 height, UINT32& x, UINT32& y, bool allowGrowth);
  70. UINT32 mInitialWidth;
  71. UINT32 mInitialHeight;
  72. UINT32 mWidth;
  73. UINT32 mHeight;
  74. UINT32 mMaxWidth;
  75. UINT32 mMaxHeight;
  76. bool mPow2;
  77. Vector<TexAtlasNode> mNodes;
  78. };
  79. /** Utility class used for texture atlas layouts. */
  80. class BS_UTILITY_EXPORT TextureAtlasUtility
  81. {
  82. public:
  83. /**
  84. * Represents a single element used as in input to TextureAtlasUtility. Usually represents a single texture.
  85. *
  86. * @note input is required to be filled in before passing it to TextureAtlasUtility.
  87. * @note output will be filled after a call to TextureAtlasUtility::createAtlasLayout().
  88. */
  89. struct Element
  90. {
  91. struct
  92. {
  93. UINT32 width, height;
  94. } input;
  95. struct
  96. {
  97. UINT32 x, y;
  98. UINT32 idx;
  99. INT32 page;
  100. } output;
  101. };
  102. /** Describes a single page of the texture atlas. */
  103. struct Page
  104. {
  105. UINT32 width, height;
  106. };
  107. /**
  108. * Creates an optimal texture layout by packing texture elements in order to end up with as little empty space
  109. * as possible. Algorithm will split elements over multiple textures if they don't fit in a single texture.
  110. *
  111. * @param[in] elements Elements to process. They need to have their input structures filled in,
  112. * and this method will fill output when it returns.
  113. * @param[in] width Initial width of the atlas texture.
  114. * @param[in] height Initial height of the atlas texture.
  115. * @param[in] maxWidth Maximum width the atlas texture is allowed to grow to, when elements don't fit.
  116. * @param[in] maxHeight Maximum height the atlas texture is allowed to grow to, when elements don't fit.
  117. * @param[in] pow2 When true the resulting atlas size will always be a power of two.
  118. * @return One or more descriptors that determine the size of the final atlas textures.
  119. * Texture elements will reference these pages with their output.page parameter.
  120. */
  121. static Vector<Page> createAtlasLayout(Vector<Element>& elements, UINT32 width, UINT32 height, UINT32 maxWidth,
  122. UINT32 maxHeight, bool pow2 = false);
  123. };
  124. /** @} */
  125. }