From 8326b110dfe2b00c43340ded9e80222252939a5c Mon Sep 17 00:00:00 2001 From: Joseph Ferano Date: Wed, 11 Oct 2023 22:49:49 +0700 Subject: [PATCH] Predefine rects where we're going to place the textures --- game/tools/texturepacker.c | 67 +++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 30 deletions(-) diff --git a/game/tools/texturepacker.c b/game/tools/texturepacker.c index 4d970bf..eabc85b 100644 --- a/game/tools/texturepacker.c +++ b/game/tools/texturepacker.c @@ -9,13 +9,16 @@ #define STB_IMAGE_WRITE_IMPLEMENTATION #include "stb_image_write.h" -struct image { +typedef struct image_t { char* filename; unsigned char* image_data; - int width; - int height; - int channels; -}; + int id, width, height, channels; +} image_t; + +typedef struct tex_rect_t { + image_t* img; + int x,y,w,h; +} tex_rect_t; int main(int argc, char* argv[]) { if (argc == 1) { @@ -26,7 +29,7 @@ int main(int argc, char* argv[]) { fprintf(stderr, "Please provide at least 2 images to pack"); exit(-1); } - struct image* images = calloc(argc - 1, sizeof(struct image)); + image_t* images = calloc(argc - 1, sizeof(image_t)); if (images == NULL) { fprintf(stderr, "Failed to alloc image data array"); exit(-1); @@ -36,7 +39,7 @@ int main(int argc, char* argv[]) { //------------------------------------- int image_count = argc - 1; for (int i = 0; i < argc - 1; i++) { - struct image* img = &images[i]; + image_t* img = &images[i]; img->filename = argv[i+1]; int result = stbi_info(img->filename, &img->width, &img->height, &img->channels); @@ -47,16 +50,20 @@ int main(int argc, char* argv[]) { } } //------------------------------------- - // Now run the packing algorithm - // Note: How to get the minimum power of 2 texture size. Note that this is still - // very inefficient because we're just naively putting them all at 0 - // x = log2(max(width, height)) - // width or height = 2 ** (x + 1) - // This is super inefficient texture packing but I just want to get it working first + // Now run the packing algorithm. This is super inefficient + // texture packing but I just want to get it working first //------------------------------------- + tex_rect_t* tex_rects = calloc(image_count, sizeof(tex_rect_t)); int totalh = 0, maxw = 0; for (int i = 0; i < image_count; i++) { + tex_rects[i] = (tex_rect_t){ + &images[i], + 0, // Put them all on the 1st column for now + totalh, + images[i].width, + images[i].height, + }; totalh += images[i].height; if (images[i].width > maxw) { maxw = images[i].width; @@ -65,7 +72,6 @@ int main(int argc, char* argv[]) { int max = totalh > maxw ? totalh : maxw; int exp = (int)log2(max) + 1; int size = (int)pow(2, exp); - unsigned char* buf = calloc(size*size*4, sizeof(char)); //------------------------------------- // Now load the data into memory, for now, let's just load all images in one go, @@ -90,24 +96,25 @@ int main(int argc, char* argv[]) { // we need to make this work, since we're "hardcoding" the positions of the textures //------------------------------------- - int atlasrow = 0; + unsigned char* buf = calloc(size*size*4, sizeof(char)); + int channels = images[0].channels; for (int i = 0; i < image_count; i++) { - int width = images[i].width; - int length = images[i].width * images[i].height * images[i].channels; - int color_row = 0; - int color_col = 0; - int c = 0; - while (c < length) { - int bidx = atlasrow * maxw * 4 + color_row; - int iidx = color_col * width * 4 + color_row; - buf[bidx] = images[i].image_data[iidx]; - color_row++; - if (color_row > width * 4) { - color_row = 0; - color_col += 1; - atlasrow += 1; + tex_rect_t rect = tex_rects[i]; + int buf_row = rect.y; + int buf_col = rect.x; + int img_row = 0; + int img_col = 0; + while (img_row < rect.h) { + int buf_idx = (buf_row * maxw + buf_col) * channels; + int img_idx = (img_row * rect.w + img_col) * channels; + for (int j = 0; j < channels; j++) { + buf[buf_idx + j] = images[i].image_data[img_idx + j]; + } + img_col++; buf_col++; + if (img_col > rect.w) { + img_col = buf_col = 0; + img_row++; buf_row++; } - c++; } }