cube_atlas.h 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. /*
  2. * Copyright 2013 Jeremie Roy. All rights reserved.
  3. * License: http://www.opensource.org/licenses/BSD-2-Clause
  4. */
  5. #ifndef CUBE_ATLAS_H_HEADER_GUARD
  6. #define CUBE_ATLAS_H_HEADER_GUARD
  7. /// Inspired from texture-atlas from freetype-gl (http://code.google.com/p/freetype-gl/)
  8. /// by Nicolas Rougier ([email protected])
  9. /// The actual implementation is based on the article by Jukka Jylänki : "A
  10. /// Thousand Ways to Pack the Bin - A Practical Approach to Two-Dimensional
  11. /// Rectangle Bin Packing", February 27, 2010.
  12. /// More precisely, this is an implementation of the Skyline Bottom-Left
  13. /// algorithm based on C++ sources provided by Jukka Jylänki at:
  14. /// http://clb.demon.fi/files/RectangleBinPack/
  15. #include <bgfx.h>
  16. struct AtlasRegion
  17. {
  18. enum Type
  19. {
  20. TYPE_GRAY = 1, // 1 component
  21. TYPE_BGRA8 = 4 // 4 components
  22. };
  23. uint16_t x, y;
  24. uint16_t width, height;
  25. uint32_t mask; //encode the region type, the face index and the component index in case of a gray region
  26. Type getType() const
  27. {
  28. return (Type) ( (mask >> 0) & 0x0000000F);
  29. }
  30. uint32_t getFaceIndex() const
  31. {
  32. return (mask >> 4) & 0x0000000F;
  33. }
  34. uint32_t getComponentIndex() const
  35. {
  36. return (mask >> 8) & 0x0000000F;
  37. }
  38. void setMask(Type _type, uint32_t _faceIndex, uint32_t _componentIndex)
  39. {
  40. mask = (_componentIndex << 8) + (_faceIndex << 4) + (uint32_t)_type;
  41. }
  42. };
  43. class Atlas
  44. {
  45. public:
  46. /// create an empty dynamic atlas (region can be updated and added)
  47. /// @param textureSize an atlas creates a texture cube of 6 faces with size equal to (textureSize*textureSize * sizeof(RGBA))
  48. /// @param maxRegionCount maximum number of region allowed in the atlas
  49. Atlas(uint16_t _textureSize, uint16_t _maxRegionsCount = 4096);
  50. /// initialize a static atlas with serialized data (region can be updated but not added)
  51. /// @param textureSize an atlas creates a texture cube of 6 faces with size equal to (textureSize*textureSize * sizeof(RGBA))
  52. /// @param textureBuffer buffer of size 6*textureSize*textureSize*sizeof(uint32_t) (will be copied)
  53. /// @param regionCount number of region in the Atlas
  54. /// @param regionBuffer buffer containing the region (will be copied)
  55. /// @param maxRegionCount maximum number of region allowed in the atlas
  56. Atlas(uint16_t _textureSize, const uint8_t* _textureBuffer, uint16_t _regionCount, const uint8_t* _regionBuffer, uint16_t _maxRegionsCount = 4096);
  57. ~Atlas();
  58. /// add a region to the atlas, and copy the content of mem to the underlying texture
  59. uint16_t addRegion(uint16_t _width, uint16_t _height, const uint8_t* _bitmapBuffer, AtlasRegion::Type _type = AtlasRegion::TYPE_BGRA8, uint16_t outline = 0);
  60. /// update a preallocated region
  61. void updateRegion(const AtlasRegion& _region, const uint8_t* _bitmapBuffer);
  62. /// Pack the UV coordinates of the four corners of a region to a vertex buffer using the supplied vertex format.
  63. /// v0 -- v3
  64. /// | | encoded in that order: v0,v1,v2,v3
  65. /// v1 -- v2
  66. /// @remark the UV are four signed short normalized components.
  67. /// @remark the x,y,z components encode cube uv coordinates. The w component encode the color channel if any.
  68. /// @param handle handle to the region we are interested in
  69. /// @param vertexBuffer address of the first vertex we want to update. Must be valid up to vertexBuffer + offset + 3*stride + 4*sizeof(int16_t), which means the buffer must contains at least 4 vertex includind the first.
  70. /// @param offset byte offset to the first uv coordinate of the vertex in the buffer
  71. /// @param stride stride between tho UV coordinates, usually size of a Vertex.
  72. void packUV(uint16_t _regionHandle, uint8_t* _vertexBuffer, uint32_t _offset, uint32_t _stride) const;
  73. void packUV(const AtlasRegion& _region, uint8_t* _vertexBuffer, uint32_t _offset, uint32_t _stride) const;
  74. /// Same as packUV but pack a whole face of the atlas cube, mostly used for debugging and visualizing atlas
  75. void packFaceLayerUV(uint32_t _idx, uint8_t* _vertexBuffer, uint32_t _offset, uint32_t _stride) const;
  76. /// Pack the vertex index of the region as 2 quad into an index buffer
  77. static void packIndex(uint16_t* _indexBuffer, uint32_t _startIndex, uint32_t _startVertex)
  78. {
  79. uint16_t* indices = &_indexBuffer[_startIndex];
  80. *indices++ = _startVertex + 0;
  81. *indices++ = _startVertex + 1;
  82. *indices++ = _startVertex + 2;
  83. *indices++ = _startVertex + 0;
  84. *indices++ = _startVertex + 2;
  85. *indices++ = _startVertex + 3;
  86. }
  87. /// return the TextureHandle (cube) of the atlas
  88. bgfx::TextureHandle getTextureHandle() const
  89. {
  90. return m_textureHandle;
  91. }
  92. //retrieve a region info
  93. const AtlasRegion& getRegion(uint16_t _handle) const
  94. {
  95. return m_regions[_handle];
  96. }
  97. /// retrieve the size of side of a texture in pixels
  98. uint16_t getTextureSize() const
  99. {
  100. return m_textureSize;
  101. }
  102. /// retrieve the usage ratio of the atlas
  103. //float getUsageRatio() const { return 0.0f; }
  104. /// retrieve the numbers of region in the atlas
  105. uint16_t getRegionCount() const
  106. {
  107. return m_regionCount;
  108. }
  109. /// retrieve a pointer to the region buffer (in order to serialize it)
  110. const AtlasRegion* getRegionBuffer() const
  111. {
  112. return m_regions;
  113. }
  114. /// retrieve the byte size of the texture
  115. uint32_t getTextureBufferSize() const
  116. {
  117. return 6 * m_textureSize * m_textureSize * 4;
  118. }
  119. /// retrieve the mirrored texture buffer (to serialize it)
  120. const uint8_t* getTextureBuffer() const
  121. {
  122. return m_textureBuffer;
  123. }
  124. private:
  125. void init();
  126. struct PackedLayer;
  127. PackedLayer* m_layers;
  128. AtlasRegion* m_regions;
  129. uint8_t* m_textureBuffer;
  130. uint32_t m_usedLayers;
  131. uint32_t m_usedFaces;
  132. bgfx::TextureHandle m_textureHandle;
  133. uint16_t m_textureSize;
  134. float m_texelSize;
  135. float m_texelOffset[2];
  136. uint16_t m_regionCount;
  137. uint16_t m_maxRegionCount;
  138. };
  139. #endif // CUBE_ATLAS_H_HEADER_GUARD