switched to command based rendering
[fishladder.git] / texsheet.c
diff --git a/texsheet.c b/texsheet.c
new file mode 100644 (file)
index 0000000..f420866
--- /dev/null
@@ -0,0 +1,214 @@
+// Copyright (C) 2021 Harry Godden (hgn) - All Rights Reserved
+
+#define VG_TOOLS
+#include "vg/vg.h"
+
+#define STB_IMAGE_IMPLEMENTATION
+#include "stb/stb_image.h"
+
+struct image_src
+{
+       int x,y,ch;
+
+       u8 *data;
+};
+
+int image_sort( const void* a, const void* b)
+{
+       struct image_src *p_a = (struct image_src *)a;
+       struct image_src *p_b = (struct image_src *)b;
+
+       if( p_a->x == p_b->x )
+               return 0;
+       else if ( p_a->x < p_b->x )
+               return 1;
+       else 
+               return -1;
+}
+
+int main( int argc, const char *argv[] )
+{
+       struct image_src *source_images = malloc( sizeof( struct image_src ) * argc );
+
+       u32 num_images = 0;
+       
+       if( argc < 4 )
+       {
+               vg_error( "Missing output file paths\n" );
+               return 0;
+       }
+
+       // Open header handle
+       // ------------------
+       FILE *fp = fopen( argv[2], "w" );
+       if( !fp )
+       {
+               vg_error( "Could not open file for writing\n" );
+               return 0;
+       }
+
+       fprintf( fp, "static enum %s_index\n{\n", argv[3] );
+
+       // Load images
+       // -----------
+       stbi_set_flip_vertically_on_load(1);
+
+       for( int i = 4; i < argc; i ++ )
+       {
+               struct image_src *src = &source_images[ num_images ];
+               src->data = (u8 *)stbi_load( argv[i], &src->x, &src->y, &src->ch, 4 );
+               
+               char name[ 256 ];
+               int j = 0; int ext = 0;
+               for( ; j < vg_list_size( name )-1; j ++ )
+               {
+                       if( argv[i][j] )
+                       {
+                               name[j] = argv[i][j];
+
+                               if( name[j] == '.' )
+                                       ext = j;
+
+                               if( name[j] == '.' || name[j] == '-' )
+                                       name[j] = '_';
+                       }
+                       else
+                               break;
+               }
+
+               if( ext )
+                       name[ext] = 0x00;
+               else
+                       name[j] = 0x00;
+
+               fprintf( fp, "\tk_sprite_%s,\n", name );
+
+               if( src->data )
+               {
+                       if( src->x != src->y )
+                       {
+                               vg_error( "Non-square images are currently not supported ('%s')\n", argv[i] );
+                               free( src->data );
+                       }
+                       else
+                               num_images ++;
+               }
+               else
+                       vg_error( "Could not decode '%s'\n", argv[i] );
+       }
+       
+       fprintf( fp, "};\n\n" );
+
+       // Sort by size
+       // ------------
+       qsort( source_images, num_images, sizeof(struct image_src), image_sort );
+
+       // Process images
+       // --------------
+       fprintf( fp, "static struct vg_sprite %s[] = \n{\n", argv[3] );
+
+       u8 *dest = (u8 *)malloc( 1024*1024*4 );
+       
+       // Clear (temp)
+       for( int i = 0; i < 1024*1024; i ++ )
+       {
+               dest[ i*4 + 0 ] = 0;
+               dest[ i*4 + 1 ] = 0;
+               dest[ i*4 + 2 ] = 128;
+               dest[ i*4 + 3 ] = 255;
+       }
+
+       struct region
+       {
+               v2i p0;
+               v2i p1;
+       }
+       region_stack[ 32 ] =
+       {
+               {
+                       .p0 = { 0, 0 },
+                       .p1 = { 1024, 1024 }
+               }
+       };
+       int stack_h = 0;
+
+       int sf = 64;
+
+       for( int i = 0; i < num_images; i ++ )
+       {
+               struct image_src *psrc = &source_images[ i ];
+
+               // Region checks
+               while( 1 )
+               {
+                       struct region *pregion = &region_stack[ stack_h ];
+
+                       if( (pregion->p0[ 0 ] + psrc->x <= pregion->p1[0]) && (pregion->p0[ 1 ] + psrc->y <= pregion->p1[1]) )
+                       {
+                               // Passed, add image and create subdivisions
+                               fprintf( fp, "\t{ %hu, %hu, %hu, %hu },\n", 
+                                       (u16)(sf * pregion->p0[0]), 
+                                       (u16)(sf * pregion->p0[1]), 
+                                       (u16)(sf * psrc->x),
+                                       (u16)(sf * psrc->y)
+                               );
+
+                               // Write image
+                               for( int y = 0; y < psrc->y; y ++ )
+                               {
+                                       int px = pregion->p0[0];
+                                       int py = pregion->p0[1] + y;
+
+                                       memcpy( &dest[ (py*1024+px) * 4 ], &psrc->data[ y*psrc->x*4 ], psrc->x*4 );
+                               }
+
+                               // Subdivisions
+                               stack_h ++;
+                               struct region *new_region = &region_stack[ stack_h ];
+
+                               new_region->p0[0] = pregion->p0[0] + psrc->x;
+                               new_region->p0[1] = pregion->p0[1];
+                               new_region->p1[0] = pregion->p1[0];
+                               new_region->p1[1] = pregion->p0[1] + psrc->y;
+
+                               pregion->p0[ 1 ] += psrc->y;
+                               break;
+                       }
+                       else
+                       {
+                               // Failed, loop up to next region if can
+                               if( stack_h == 0 )
+                               {
+                                       vg_error( "Could not fit image %d. Pack failed\n", i );
+
+                                       goto IL_END_ERR;
+                               }
+                               else
+                                       stack_h --;
+                       }
+               }
+       }
+
+IL_END_ERR:
+       fprintf( fp, "};" );
+       fclose( fp );
+
+       // Write output
+       // ------------
+       qoi_write( argv[1], dest, &(qoi_desc){
+               .width = 1024,
+               .height = 1024,
+               .channels = 4,
+               .colorspace = QOI_SRGB
+       });
+
+       // Free
+       // ----
+       for( int i = 0; i < num_images; i ++ )
+               free( source_images[ i ].data );
+       free( dest );
+       free( source_images );
+
+       vg_success( "Processed %u images\n", num_images );
+
+}