BsTextureAtlasLayout.h 5.2 KB

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