Expand dynamic atlas without rearranging previous glyphs
This commit is contained in:
parent
dadc65c85c
commit
a99a4575a4
|
|
@ -27,7 +27,7 @@ public:
|
|||
/// Creates with a configured generator. The generator must not contain any prior glyphs!
|
||||
explicit DynamicAtlas(AtlasGenerator &&generator);
|
||||
/// Adds a batch of glyphs. Adding more than one glyph at a time may improve packing efficiency
|
||||
ChangeFlags add(GlyphGeometry *glyphs, int count);
|
||||
ChangeFlags add(GlyphGeometry *glyphs, int count, bool allowRearrange = false);
|
||||
/// Allows access to generator. Do not add glyphs to the generator directly!
|
||||
AtlasGenerator & atlasGenerator();
|
||||
const AtlasGenerator & atlasGenerator() const;
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ template <class AtlasGenerator>
|
|||
DynamicAtlas<AtlasGenerator>::DynamicAtlas(AtlasGenerator &&generator) : generator((AtlasGenerator &&) generator), glyphCount(0), side(0), totalArea(0), padding(0) { }
|
||||
|
||||
template <class AtlasGenerator>
|
||||
typename DynamicAtlas<AtlasGenerator>::ChangeFlags DynamicAtlas<AtlasGenerator>::add(GlyphGeometry *glyphs, int count) {
|
||||
typename DynamicAtlas<AtlasGenerator>::ChangeFlags DynamicAtlas<AtlasGenerator>::add(GlyphGeometry *glyphs, int count, bool allowRearrange) {
|
||||
ChangeFlags changeFlags = 0;
|
||||
int start = rectangles.size();
|
||||
for (int i = 0; i < count; ++i) {
|
||||
|
|
@ -29,16 +29,22 @@ typename DynamicAtlas<AtlasGenerator>::ChangeFlags DynamicAtlas<AtlasGenerator>:
|
|||
}
|
||||
if ((int) rectangles.size() > start) {
|
||||
int packerStart = start;
|
||||
while (packer.pack(rectangles.data()+packerStart, rectangles.size()-packerStart) > 0) {
|
||||
int remaining;
|
||||
while ((remaining = packer.pack(rectangles.data()+packerStart, rectangles.size()-packerStart)) > 0) {
|
||||
side = (side+!side)<<1;
|
||||
while (side*side < totalArea)
|
||||
side <<= 1;
|
||||
packer = RectanglePacker(side+padding, side+padding);
|
||||
packerStart = 0;
|
||||
if (allowRearrange) {
|
||||
packer = RectanglePacker(side+padding, side+padding);
|
||||
packerStart = 0;
|
||||
} else {
|
||||
packer.expand(side+padding, side+padding);
|
||||
packerStart = rectangles.size()-remaining;
|
||||
}
|
||||
changeFlags |= RESIZED;
|
||||
}
|
||||
if (packerStart < start) {
|
||||
for (int i = 0; i < start; ++i) {
|
||||
for (int i = packerStart; i < start; ++i) {
|
||||
Remap &remap = remapBuffer[i];
|
||||
remap.source = remap.target;
|
||||
remap.target.x = rectangles[i].x;
|
||||
|
|
|
|||
|
|
@ -25,12 +25,26 @@ RectanglePacker::RectanglePacker(int width, int height) {
|
|||
spaces.push_back(Rectangle { 0, 0, width, height });
|
||||
}
|
||||
|
||||
void RectanglePacker::expand(int width, int height) {
|
||||
if (width > 0 && height > 0) {
|
||||
int oldWidth = 0, oldHeight = 0;
|
||||
for (const Rectangle &space : spaces) {
|
||||
if (space.x+space.w > oldWidth)
|
||||
oldWidth = space.x+space.w;
|
||||
if (space.y+space.h > oldHeight)
|
||||
oldHeight = space.y+space.h;
|
||||
}
|
||||
spaces.push_back(Rectangle { 0, 0, width, height });
|
||||
splitSpace(int(spaces.size()-1), oldWidth, oldHeight);
|
||||
}
|
||||
}
|
||||
|
||||
void RectanglePacker::splitSpace(int index, int w, int h) {
|
||||
Rectangle space = spaces[index];
|
||||
removeFromUnorderedVector(spaces, index);
|
||||
Rectangle a = { space.x, space.y+h, w, space.h-h };
|
||||
Rectangle b = { space.x+w, space.y, space.w-w, h };
|
||||
if (w*(space.h-h) <= h*(space.w-w))
|
||||
if (w*(space.h-h) < h*(space.w-w))
|
||||
a.w = space.w;
|
||||
else
|
||||
b.h = space.h;
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ class RectanglePacker {
|
|||
public:
|
||||
RectanglePacker();
|
||||
RectanglePacker(int width, int height);
|
||||
/// Expands the packing area - both width and height must be greater or equal to the previous value
|
||||
void expand(int width, int height);
|
||||
/// Packs the rectangle array, returns how many didn't fit (0 on success)
|
||||
int pack(Rectangle *rectangles, int count);
|
||||
int pack(OrientedRectangle *rectangles, int count);
|
||||
|
|
|
|||
Loading…
Reference in New Issue