BsTextureAtlasLayout.h 5.0 KB

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