| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- /*
- * Copyright 2013 Jeremie Roy. All rights reserved.
- * License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE
- */
- #ifndef CUBE_ATLAS_H_HEADER_GUARD
- #define CUBE_ATLAS_H_HEADER_GUARD
- /// Inspired from texture-atlas from freetype-gl (http://code.google.com/p/freetype-gl/)
- /// by Nicolas Rougier ([email protected])
- /// The actual implementation is based on the article by Jukka Jylänki : "A
- /// Thousand Ways to Pack the Bin - A Practical Approach to Two-Dimensional
- /// Rectangle Bin Packing", February 27, 2010.
- /// More precisely, this is an implementation of the Skyline Bottom-Left
- /// algorithm based on C++ sources provided by Jukka Jylänki at:
- /// http://clb.demon.fi/files/RectangleBinPack/
- #include <bgfx/bgfx.h>
- struct AtlasRegion
- {
- enum Type
- {
- TYPE_GRAY = 1, // 1 component
- TYPE_BGRA8 = 4 // 4 components
- };
- uint16_t x, y;
- uint16_t width, height;
- uint32_t mask; //encode the region type, the face index and the component index in case of a gray region
- Type getType() const
- {
- return (Type) ( (mask >> 0) & 0x0000000F);
- }
- uint32_t getFaceIndex() const
- {
- return (mask >> 4) & 0x0000000F;
- }
- uint32_t getComponentIndex() const
- {
- return (mask >> 8) & 0x0000000F;
- }
- void setMask(Type _type, uint32_t _faceIndex, uint32_t _componentIndex)
- {
- mask = (_componentIndex << 8) + (_faceIndex << 4) + (uint32_t)_type;
- }
- };
- class Atlas
- {
- public:
- /// create an empty dynamic atlas (region can be updated and added)
- /// @param textureSize an atlas creates a texture cube of 6 faces with size equal to (textureSize*textureSize * sizeof(RGBA) )
- /// @param maxRegionCount maximum number of region allowed in the atlas
- Atlas(uint16_t _textureSize, uint16_t _maxRegionsCount = 4096);
- /// initialize a static atlas with serialized data (region can be updated but not added)
- /// @param textureSize an atlas creates a texture cube of 6 faces with size equal to (textureSize*textureSize * sizeof(RGBA) )
- /// @param textureBuffer buffer of size 6*textureSize*textureSize*sizeof(uint32_t) (will be copied)
- /// @param regionCount number of region in the Atlas
- /// @param regionBuffer buffer containing the region (will be copied)
- /// @param maxRegionCount maximum number of region allowed in the atlas
- Atlas(uint16_t _textureSize, const uint8_t* _textureBuffer, uint16_t _regionCount, const uint8_t* _regionBuffer, uint16_t _maxRegionsCount = 4096);
- ~Atlas();
- /// add a region to the atlas, and copy the content of mem to the underlying texture
- uint16_t addRegion(uint16_t _width, uint16_t _height, const uint8_t* _bitmapBuffer, AtlasRegion::Type _type = AtlasRegion::TYPE_BGRA8, uint16_t outline = 0);
- /// update a preallocated region
- void updateRegion(const AtlasRegion& _region, const uint8_t* _bitmapBuffer);
- /// Pack the UV coordinates of the four corners of a region to a vertex buffer using the supplied vertex format.
- /// v0 -- v3
- /// | | encoded in that order: v0,v1,v2,v3
- /// v1 -- v2
- /// @remark the UV are four signed short normalized components.
- /// @remark the x,y,z components encode cube uv coordinates. The w component encode the color channel if any.
- /// @param handle handle to the region we are interested in
- /// @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.
- /// @param offset byte offset to the first uv coordinate of the vertex in the buffer
- /// @param stride stride between tho UV coordinates, usually size of a Vertex.
- void packUV(uint16_t _regionHandle, uint8_t* _vertexBuffer, uint32_t _offset, uint32_t _stride) const;
- void packUV(const AtlasRegion& _region, uint8_t* _vertexBuffer, uint32_t _offset, uint32_t _stride) const;
- /// Same as packUV but pack a whole face of the atlas cube, mostly used for debugging and visualizing atlas
- void packFaceLayerUV(uint32_t _idx, uint8_t* _vertexBuffer, uint32_t _offset, uint32_t _stride) const;
- /// return the TextureHandle (cube) of the atlas
- bgfx::TextureHandle getTextureHandle() const
- {
- return m_textureHandle;
- }
- //retrieve a region info
- const AtlasRegion& getRegion(uint16_t _handle) const
- {
- return m_regions[_handle];
- }
- /// retrieve the size of side of a texture in pixels
- uint16_t getTextureSize() const
- {
- return m_textureSize;
- }
- /// retrieve the usage ratio of the atlas
- //float getUsageRatio() const { return 0.0f; }
- /// retrieve the numbers of region in the atlas
- uint16_t getRegionCount() const
- {
- return m_regionCount;
- }
- /// retrieve a pointer to the region buffer (in order to serialize it)
- const AtlasRegion* getRegionBuffer() const
- {
- return m_regions;
- }
- /// retrieve the byte size of the texture
- uint32_t getTextureBufferSize() const
- {
- return 6 * m_textureSize * m_textureSize * 4;
- }
- /// retrieve the mirrored texture buffer (to serialize it)
- const uint8_t* getTextureBuffer() const
- {
- return m_textureBuffer;
- }
- private:
- struct PackedLayer;
- PackedLayer* m_layers;
- AtlasRegion* m_regions;
- uint8_t* m_textureBuffer;
- uint32_t m_usedLayers;
- uint32_t m_usedFaces;
- bgfx::TextureHandle m_textureHandle;
- uint16_t m_textureSize;
- float m_texelSize;
- uint16_t m_regionCount;
- uint16_t m_maxRegionCount;
- };
- #endif // CUBE_ATLAS_H_HEADER_GUARD
|