23 TextureAtlas::TextureAtlas(
const string&
id): atlasTextureId(id) {
28 atlasTextureEntity.texture->releaseReference();
59 .textureIdx = textureIdx,
115 vector<AtlasTexture> atlasTextures;
117 auto totalHeight = 0;
119 atlasTextureEntity.left = -1;
120 atlasTextureEntity.height = -1;
121 atlasTextureEntity.line = -1;
122 if (atlasTextureEntity.texture->getTextureWidth() > atlasTextureEntity.texture->getTextureHeight()) {
124 atlasTextureEntity.width = atlasTextureEntity.texture->getTextureHeight();
125 atlasTextureEntity.height = atlasTextureEntity.texture->getTextureWidth();
128 atlasTextureEntity.width = atlasTextureEntity.texture->getTextureWidth();
129 atlasTextureEntity.height = atlasTextureEntity.texture->getTextureHeight();
131 totalWidth+= atlasTextureEntity.texture->getTextureWidth();
132 totalHeight+= atlasTextureEntity.texture->getTextureHeight();
133 atlasTextures.push_back(atlasTextureEntity);
138 atlasTextures.begin(),
141 return atlasTexture1.height > atlasTexture2.height;
146 auto atlasTextureWidth = 4096;
153 auto heigthColumnMax = 0;
154 for (
auto& atlasTextureEntity: atlasTextures) {
155 atlasTextureEntity.left = left;
156 atlasTextureEntity.top = top;
157 atlasTextureEntity.line = line;
158 left+= atlasTextureEntity.width;
159 heigthColumnMax = Math::max(heigthColumnMax, atlasTextureEntity.height);
160 if (left >= atlasTextureWidth) {
162 top+= heigthColumnMax;
168 atlasTextureWidth = left;
169 auto textureWidth = 1;
170 while (textureWidth < atlasTextureWidth) textureWidth*= 2;
171 atlasTextureWidth = textureWidth;
176 for (
auto i = 0; i < atlasTextures.size(); i++) {
177 auto pushedAtlasTextureTop = -1;
178 auto& atlasTextureEntity = atlasTextures[i];
180 for (
auto j = 0; j < i; j++) {
181 const auto& atlasTextureEntityCompare = atlasTextures[j];
182 if (atlasTextureEntityCompare.line != atlasTextureEntity.line - 1)
continue;
184 if (atlasTextureEntityCompare.left >= atlasTextureEntity.left + atlasTextureEntity.width)
continue;
185 if (atlasTextureEntity.left >= atlasTextureEntityCompare.left + atlasTextureEntityCompare.width)
continue;
187 pushedAtlasTextureTop = Math::max(pushedAtlasTextureTop, atlasTextureEntityCompare.top + atlasTextureEntityCompare.height);
189 if (pushedAtlasTextureTop != -1) atlasTextureEntity.top = pushedAtlasTextureTop;
193 auto atlasTextureHeight = 0;
194 for (
const auto& atlasTextureEntity: atlasTextures) {
195 atlasTextureHeight = Math::max(atlasTextureHeight, atlasTextureEntity.top + atlasTextureEntity.height);
200 auto textureHeight = 1;
201 while (textureHeight < atlasTextureHeight) textureHeight*= 2;
202 atlasTextureHeight = textureHeight;
206 auto atlasTextureByteBuffer =
ByteBuffer(atlasTextureWidth * atlasTextureHeight * 4);
207 auto atlasTextureBuffer = atlasTextureByteBuffer.getBuffer();
210 for (
const auto& atlasTextureEntity: atlasTextures) {
211 auto atlasLeft = atlasTextureEntity.left;
212 auto atlasTop = atlasTextureEntity.top;
213 auto texture = atlasTextureEntity.texture;
214 auto textureData = texture->getRGBTextureData();
215 auto textureBytesPerPixel = texture->getRGBDepthBitsPerPixel() / 8;
216 auto textureWidth = texture->getTextureWidth();
217 auto textureHeight = texture->getTextureHeight();
218 for (
auto y = 0; y < textureHeight; y++) {
219 for (
auto x = 0; x < textureWidth; x++) {
220 auto r = textureData.get(y * textureWidth * textureBytesPerPixel + x * textureBytesPerPixel + 0);
221 auto g = textureData.get(y * textureWidth * textureBytesPerPixel + x * textureBytesPerPixel + 1);
222 auto b = textureData.get(y * textureWidth * textureBytesPerPixel + x * textureBytesPerPixel + 2);
223 auto a = textureBytesPerPixel == 4?textureData.get(y * textureWidth * textureBytesPerPixel + x * textureBytesPerPixel + 3):0xff;
225 atlasTextureBuffer[(atlasTop + textureHeight - 1 - y) * atlasTextureWidth * 4 + (atlasLeft + x) * 4 + 0] = r;
226 atlasTextureBuffer[(atlasTop + textureHeight - 1 - y) * atlasTextureWidth * 4 + (atlasLeft + x) * 4 + 1] = g;
227 atlasTextureBuffer[(atlasTop + textureHeight - 1 - y) * atlasTextureWidth * 4 + (atlasLeft + x) * 4 + 2] = b;
228 atlasTextureBuffer[(atlasTop + textureHeight - 1 - y) * atlasTextureWidth * 4 + (atlasLeft + x) * 4 + 3] = a;
231 atlasTextureBuffer[(atlasTop + x) * atlasTextureWidth * 4 + (atlasLeft + textureHeight - 1 - y) * 4 + 0] = r;
232 atlasTextureBuffer[(atlasTop + x) * atlasTextureWidth * 4 + (atlasLeft + textureHeight - 1 - y) * 4 + 1] = g;
233 atlasTextureBuffer[(atlasTop + x) * atlasTextureWidth * 4 + (atlasLeft + textureHeight - 1 - y) * 4 + 2] = b;
234 atlasTextureBuffer[(atlasTop + x) * atlasTextureWidth * 4 + (atlasLeft + textureHeight - 1 - y) * 4 + 3] = a;
243 Texture::TEXTUREDEPTH_RGBA,
244 Texture::TEXTUREFORMAT_RGBA,
245 atlasTextureWidth, atlasTextureHeight,
246 atlasTextureWidth, atlasTextureHeight,
247 Texture::TEXTUREFORMAT_RGBA,
248 atlasTextureByteBuffer
262 "TextureAtlas::update(): have texture: " + atlasTextureEntity.texture->getId() +
", " +
263 "left: " + to_string(atlasTextureEntity.left) +
", " +
264 "top: " + to_string(atlasTextureEntity.top) +
", " +
265 "width: " + to_string(atlasTextureEntity.width) +
", " +
266 "height: " + to_string(atlasTextureEntity.height) +
", " +
267 "orientation: " + to_string(atlasTextureEntity.orientation)
const string & getId() const
uint16_t getTextureHeight() const
uint16_t getTextureWidth() const
void setUseCompression(bool useCompression)
Set if to use compression.
void setUseMipMap(bool useMipMap)
Set if to use mip map.
static void println()
Print new line to console.
virtual void releaseReference()
Releases a reference, thus decrementing the counter and delete it if reference counter is zero.
virtual void acquireReference()
Acquires a reference, incrementing the counter.
void removeTexture(Texture *texture)
Remove texture.
~TextureAtlas()
Public destructor.
unordered_map< Texture *, int > textureReferenceCounter
vector< int > freeTextureIds
unordered_map< Texture *, int > textureToAtlasTextureIdxMapping
unordered_map< int, AtlasTexture > atlasTextureIdxToAtlasTextureMapping
int addTexture(Texture *texture)
Add texture.
static constexpr bool VERBOSE
int getTextureIdx(Texture *texture)
Returns specific atlas texture index within atlas.
static constexpr int TEXTURE_IDX_NONE
void update()
Update texture atlas.