mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-01 14:58:14 +00:00
AtlasGen: Separate pack and resolve steps
This commit is contained in:
1 parent
55d53bd29a
commit
915a88df60
4 files changed
+25
-11
No files matched your search
@@ -100,12 +100,11 @@ inline bool CompareByArea(const Data& lhs, const Data& rhs) {
|
||||
return lhs.w * lhs.h > rhs.w * rhs.h;
|
||||
}
|
||||
|
||||
std::vector<Data> Bucket::Resolve(int image_width, Image *dest) {
|
||||
void Bucket::Pack(int image_width) {
|
||||
// Place all the little images - whatever they are.
|
||||
// Uses greedy fill algorithm. Slow but works surprisingly well, CPUs are fast.
|
||||
ImageU8 masq;
|
||||
masq.resize(image_width, 1);
|
||||
dest->resize(image_width, 1);
|
||||
|
||||
// image_width is set to the square root of the total area of all images.
|
||||
// We shouldn't need more than twice that in height (more likely much less).
|
||||
@@ -120,11 +119,10 @@ std::vector<Data> Bucket::Resolve(int image_width, Image *dest) {
|
||||
int idy = (int)data[i].h;
|
||||
if (idx > 1 && idy > 1) {
|
||||
assert(idx <= image_width);
|
||||
for (int ty = 0; ty < maxHeight - 1; ty++) { // TODO: Maybe remove this limit?
|
||||
if (ty + idy + 1 > (int)dest->height()) {
|
||||
for (int ty = 0; ty < maxHeight - 1; ty++) {
|
||||
if (ty + idy + 1 > (int)masq.height()) {
|
||||
// Every 16 lines of new space needed, grow the image.
|
||||
masq.resize(image_width, ty + idy + 16);
|
||||
dest->resize(image_width, ty + idy + 16);
|
||||
}
|
||||
// Brute force packing.
|
||||
int sz = (int)data[i].w;
|
||||
@@ -163,11 +161,16 @@ std::vector<Data> Bucket::Resolve(int image_width, Image *dest) {
|
||||
// Sort the data back by ID.
|
||||
std::sort(data.begin(), data.end(), CompareByID);
|
||||
|
||||
w = image_width;
|
||||
h = masq.height();
|
||||
}
|
||||
|
||||
std::vector<Data> Bucket::Resolve(Image *dest) {
|
||||
dest->resize(w, h);
|
||||
// Actually copy the image data in place, after doing the layout.
|
||||
for (int i = 0; i < (int)data.size(); i++) {
|
||||
dest->copyfrom(images[i], data[i].sx, data[i].sy, data[i].redToWhiteAlpha);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
@@ -119,12 +119,17 @@ struct Data {
|
||||
struct Bucket {
|
||||
std::vector<Image> images;
|
||||
std::vector<Data> data;
|
||||
int w = 0;
|
||||
int h = 0;
|
||||
|
||||
void AddItem(Image &&img, const Data &dat) {
|
||||
images.emplace_back(std::move(img));
|
||||
data.emplace_back(dat);
|
||||
}
|
||||
void AddImage(Image &&img, int id);
|
||||
std::vector<Data> Resolve(int image_width, Image *dest);
|
||||
|
||||
void Pack(int image_width);
|
||||
std::vector<Data> Resolve(Image *dest);
|
||||
};
|
||||
|
||||
AtlasImage ToAtlasImage(int id, std::string_view name, float tw, float th, const std::vector<Data> &results);
|
||||
+6
-2
@@ -385,8 +385,12 @@ static bool GenerateUIAtlasImage(Atlas *atlas, float dpiScale, Image *dest, int
|
||||
int imageWidth = RoundToNextPowerOf2((int)sqrtf(area));
|
||||
|
||||
Instant bucketStart = Instant::Now();
|
||||
std::vector<Data> results = bucket.Resolve(imageWidth, dest);
|
||||
INFO_LOG(Log::G3D, " - Bucketed %zu images in %.2f ms (final image size: %dx%d)", results.size(), bucketStart.ElapsedMs(), dest->width(), dest->height());
|
||||
bucket.Pack(imageWidth);
|
||||
INFO_LOG(Log::G3D, " - Packed in %.2f ms (image size: %dx%d)", bucketStart.ElapsedMs(), bucket.w, bucket.h);
|
||||
|
||||
Instant resolveStart = Instant::Now();
|
||||
std::vector<Data> results = bucket.Resolve(dest);
|
||||
INFO_LOG(Log::G3D, " - Resolved %zu images in %.2f ms (final image size: %dx%d)", results.size(), resolveStart.ElapsedMs(), dest->width(), dest->height());
|
||||
|
||||
_dbg_assert_(!results.empty());
|
||||
// Fill out the atlas structure.
|
||||
|
||||
@@ -652,9 +652,11 @@ int GenerateFromScript(const char *script_file, const char *atlas_name, bool hig
|
||||
// Place the subimages onto the main texture. Also writes to png.
|
||||
Image dest;
|
||||
// Place things on the bitmap.
|
||||
printf("Resolving...\n");
|
||||
|
||||
std::vector<Data> results = bucket.Resolve(image_width, &dest);
|
||||
printf("Packing...\n");
|
||||
bucket.Pack(image_width);
|
||||
printf("Resolving...\n");
|
||||
std::vector<Data> results = bucket.Resolve(&dest);
|
||||
if (highcolor) {
|
||||
printf("Writing .ZIM %ix%i RGBA8888...\n", dest.width(), dest.height());
|
||||
dest.SaveZIM(image_name.c_str(), ZIM_RGBA8888 | ZIM_ZSTD_COMPRESSED);
|
||||
|
||||
Reference in new issue
Block a user