diff --git a/dtool/pptempl/Template.models.pp b/dtool/pptempl/Template.models.pp index 56b5d10a8f..291422293a 100644 --- a/dtool/pptempl/Template.models.pp +++ b/dtool/pptempl/Template.models.pp @@ -392,6 +392,14 @@ fix-pal : pi : egg-palettize $[PALETTIZE_OPTS] -a $[texattrib_file] -pi +# +# pal-stats : report palettization statistics to standard output for the +# user's perusal. +# +pal-stats : + egg-palettize $[PALETTIZE_OPTS] -a $[texattrib_file] -s +stats-pal : pal-stats + // Somehow, something in the cttools confuses some shells, so that // when we are attached, 'cd foo' doesn't work, but 'cd ./foo' does. // Weird. We get around this by putting a ./ in front of each cd diff --git a/panda/src/downloader/extractor.cxx b/panda/src/downloader/extractor.cxx index 1cab73d80a..1b4572ca0e 100644 --- a/panda/src/downloader/extractor.cxx +++ b/panda/src/downloader/extractor.cxx @@ -10,6 +10,7 @@ #include "config_downloader.h" #include +#include //////////////////////////////////////////////////////////////////// // Defines diff --git a/panda/src/gobj/config_gobj.cxx b/panda/src/gobj/config_gobj.cxx index 9b76201622..aa5e5f3cdd 100644 --- a/panda/src/gobj/config_gobj.cxx +++ b/panda/src/gobj/config_gobj.cxx @@ -18,6 +18,7 @@ #include "texture.h" #include +#include Configure(config_gobj); NotifyCategoryDef(gobj, ""); @@ -30,6 +31,27 @@ NotifyCategoryDef(gobj, ""); // necessary, so that neither dimension is larger than this value. const int max_texture_dimension = config_gobj.GetInt("max-texture-dimension", -1); +// Set textures-power-2 to force texture dimensions to a power of two. +// If this is "up" or "down", the textures will be scaled up or down +// to the next power of two, as indicated; otherwise, if this is #t, +// the textures will be scaled down. If this is #f or unspecified, +// the textures will be left at whatever size they are. + +// These are filled in by the ConfigureFn block, below. +bool textures_up_power_2 = false; +bool textures_down_power_2 = false; + +// Set textures-square to force texture dimensions to a square aspect +// ratio. This works similarly to textures-power-2, above. If this +// is "up" or "down", the textures will be scaled up or down to the +// containing square or the inscribed square, respectively; otherwise, +// if this is #t, the textures will be scaled down. If this is #f or +// unspecified, the textures will be left at whatever size they are. + +// These are filled in by the ConfigureFn block, below. +bool textures_up_square = false; +bool textures_down_square = false; + // Set this to specify how textures should be written into Bam files. // Currently, the options are: @@ -59,6 +81,34 @@ parse_texture_mode(const string &mode) { ConfigureFn(config_gobj) { string texture_mode = config_util.GetString("bam-texture-mode", "relative"); bam_texture_mode = parse_texture_mode(texture_mode); + + string textures_power_2 = config_gobj.GetString("textures-power-2", ""); + if (cmp_nocase(textures_power_2, "up") == 0) { + textures_up_power_2 = true; + textures_down_power_2 = false; + + } else if (cmp_nocase(textures_power_2, "down") == 0) { + textures_up_power_2 = false; + textures_down_power_2 = true; + + } else { + textures_up_power_2 = false; + textures_down_power_2 = config_gobj.GetBool("textures-power-2", false); + } + + string textures_square = config_gobj.GetString("textures-square", ""); + if (cmp_nocase(textures_square, "up") == 0) { + textures_up_square = true; + textures_down_square = false; + + } else if (cmp_nocase(textures_square, "down") == 0) { + textures_up_square = false; + textures_down_square = true; + + } else { + textures_up_square = false; + textures_down_square = config_gobj.GetBool("textures-square", false); + } Fog::init_type(); Geom::init_type(); diff --git a/panda/src/gobj/config_gobj.h b/panda/src/gobj/config_gobj.h index d9eb9c5a92..96f45ce52f 100644 --- a/panda/src/gobj/config_gobj.h +++ b/panda/src/gobj/config_gobj.h @@ -13,6 +13,10 @@ NotifyCategoryDecl(gobj, EXPCL_PANDA, EXPTP_PANDA); // Configure variables for gobj package. extern EXPCL_PANDA const int max_texture_dimension; +extern EXPCL_PANDA bool textures_up_power_2; +extern EXPCL_PANDA bool textures_down_power_2; +extern EXPCL_PANDA bool textures_up_square; +extern EXPCL_PANDA bool textures_down_square; enum BamTextureMode { BTM_fullpath, diff --git a/panda/src/gobj/texture.cxx b/panda/src/gobj/texture.cxx index df6516d2eb..c3a476d7b4 100644 --- a/panda/src/gobj/texture.cxx +++ b/panda/src/gobj/texture.cxx @@ -24,6 +24,78 @@ //////////////////////////////////////////////////////////////////// TypeHandle Texture::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: up_to_power_2 +// Description: Returns the smallest power of 2 greater than or equal +// to value. +//////////////////////////////////////////////////////////////////// +static int +up_to_power_2(int value) { + int x = 1; + while (x < value) { + x = (x << 1); + } + return x; +} + +//////////////////////////////////////////////////////////////////// +// Function: down_to_power_2 +// Description: Returns the largest power of 2 less than or equal +// to value. +//////////////////////////////////////////////////////////////////// +static int +down_to_power_2(int value) { + int x = 1; + while ((x << 1) <= value) { + x = (x << 1); + } + return x; +} + +//////////////////////////////////////////////////////////////////// +// Function: consider_rescale +// Description: Scales the PNMImage according to the whims of the +// Configrc file. +//////////////////////////////////////////////////////////////////// +static void +consider_rescale(PNMImage &pnmimage, const string &name) { + int new_x_size = pnmimage.get_x_size(); + int new_y_size = pnmimage.get_y_size(); + + if (textures_down_power_2) { + new_x_size = down_to_power_2(new_x_size); + new_y_size = down_to_power_2(new_y_size); + } else if (textures_up_power_2) { + new_x_size = up_to_power_2(new_x_size); + new_y_size = up_to_power_2(new_y_size); + } + + if (textures_down_square) { + new_x_size = new_y_size = min(new_x_size, new_y_size); + } else if (textures_up_square) { + new_x_size = new_y_size = max(new_x_size, new_y_size); + } + + if (max_texture_dimension > 0) { + new_x_size = min(new_x_size, max_texture_dimension); + new_y_size = min(new_y_size, max_texture_dimension); + } + + if (pnmimage.get_x_size() != new_x_size || + pnmimage.get_y_size() != new_y_size) { + gobj_cat.info() + << "Automatically rescaling " << name << " from " + << pnmimage.get_x_size() << " by " << pnmimage.get_y_size() << " to " + << new_x_size << " by " << new_y_size << "\n"; + + PNMImage scaled(new_x_size, new_y_size, pnmimage.get_num_channels(), + pnmimage.get_maxval(), pnmimage.get_type()); + scaled.quick_filter_from(pnmimage); + pnmimage = scaled; + } +} + //////////////////////////////////////////////////////////////////// // Function: Constructor // Access: @@ -56,8 +128,8 @@ Texture:: // Access: // Description: //////////////////////////////////////////////////////////////////// -bool Texture::read(const string& name) -{ +bool Texture:: +read(const string& name) { PNMImage pnmimage; if (!pnmimage.read(name)) { @@ -66,21 +138,8 @@ bool Texture::read(const string& name) return false; } - if (max_texture_dimension > 0 && - (pnmimage.get_x_size() > max_texture_dimension || - pnmimage.get_y_size() > max_texture_dimension)) { - int new_xsize = min(pnmimage.get_x_size(), max_texture_dimension); - int new_ysize = min(pnmimage.get_y_size(), max_texture_dimension); - gobj_cat.info() - << "Automatically rescaling " << name << " from " - << pnmimage.get_x_size() << " by " << pnmimage.get_y_size() << " to " - << new_xsize << " by " << new_ysize << "\n"; - - PNMImage scaled(new_xsize, new_ysize, pnmimage.get_num_channels(), - pnmimage.get_maxval(), pnmimage.get_type()); - scaled.gaussian_filter_from(0.5, pnmimage); - pnmimage = scaled; - } + // Check to see if we need to scale it. + consider_rescale(pnmimage, name); set_name(name); clear_alpha_name(); @@ -93,7 +152,8 @@ bool Texture::read(const string& name) // Description: Combine a 3-component image with a grayscale image // to get a 4-component image //////////////////////////////////////////////////////////////////// -bool Texture::read(const string &name, const string &gray) { +bool Texture:: +read(const string &name, const string &gray) { PNMImage pnmimage; if (!pnmimage.read(name)) { gobj_cat.error() @@ -108,56 +168,28 @@ bool Texture::read(const string &name, const string &gray) { return false; } - if (max_texture_dimension > 0 && - (pnmimage.get_x_size() > max_texture_dimension || - pnmimage.get_y_size() > max_texture_dimension)) { - int new_xsize = min(pnmimage.get_x_size(), max_texture_dimension); - int new_ysize = min(pnmimage.get_y_size(), max_texture_dimension); - gobj_cat.info() - << "Automatically rescaling " << name << " from " - << pnmimage.get_x_size() << " by " << pnmimage.get_y_size() << " to " - << new_xsize << " by " << new_ysize << "\n"; + consider_rescale(pnmimage, name); - PNMImage scaled(new_xsize, new_ysize, pnmimage.get_num_channels(), - pnmimage.get_maxval(), pnmimage.get_type()); - scaled.gaussian_filter_from(0.5, pnmimage); - pnmimage = scaled; - } - - // Now do the same for the grayscale image - if (max_texture_dimension > 0 && - (grayimage.get_x_size() > max_texture_dimension || - grayimage.get_y_size() > max_texture_dimension)) { - int new_xsize = min(grayimage.get_x_size(), max_texture_dimension); - int new_ysize = min(grayimage.get_y_size(), max_texture_dimension); + // The grayscale (alpha channel) image must be the same size as the + // main image. + if (pnmimage.get_x_size() != grayimage.get_x_size() || + pnmimage.get_y_size() != grayimage.get_y_size()) { gobj_cat.info() << "Automatically rescaling " << gray << " from " << grayimage.get_x_size() << " by " << grayimage.get_y_size() << " to " - << new_xsize << " by " << new_ysize << "\n"; + << pnmimage.get_x_size() << " by " << pnmimage.get_y_size() << "\n"; - PNMImage scaled(new_xsize, new_ysize, pnmimage.get_num_channels(), - pnmimage.get_maxval(), pnmimage.get_type()); - scaled.gaussian_filter_from(0.5, pnmimage); - pnmimage = scaled; - } - - // Make sure the 2 images are the same size - int xsize = pnmimage.get_x_size(); - int ysize = pnmimage.get_y_size(); - int gxsize = grayimage.get_x_size(); - int gysize = grayimage.get_y_size(); - if ((xsize != gxsize) || (ysize != gysize)) { - gobj_cat.error() - << "Texture::read() - grayscale image not the same size as original - " - << "orig = " << xsize << "x" << ysize << " - gray = " << gxsize - << "x" << gysize << endl; - return false; + PNMImage scaled(pnmimage.get_x_size(), pnmimage.get_y_size(), + grayimage.get_num_channels(), + grayimage.get_maxval(), grayimage.get_type()); + scaled.quick_filter_from(grayimage); + grayimage = scaled; } // Make the original image a 4-component image pnmimage.add_alpha(); - for (int x = 0; x < xsize; x++) { - for (int y = 0; y < ysize; y++) { + for (int x = 0; x < pnmimage.get_x_size(); x++) { + for (int y = 0; y < pnmimage.get_y_size(); y++) { pnmimage.set_alpha(x, y, grayimage.get_gray(x, y)); } } diff --git a/pandatool/src/egg-palettize/paletteImage.cxx b/pandatool/src/egg-palettize/paletteImage.cxx index e79c5833d1..cd6d84281c 100644 --- a/pandatool/src/egg-palettize/paletteImage.cxx +++ b/pandatool/src/egg-palettize/paletteImage.cxx @@ -636,7 +636,8 @@ get_image() { } } - nout << "Generating new " << FilenameUnifier::make_user_filename(get_filename()) << "\n"; + nout << "Generating new " + << FilenameUnifier::make_user_filename(get_filename()) << "\n"; // We won't be using this any more. _cleared_regions.clear(); diff --git a/pandatool/src/egg-palettize/textureImage.cxx b/pandatool/src/egg-palettize/textureImage.cxx index 6d364c94d6..7c49d9bff5 100644 --- a/pandatool/src/egg-palettize/textureImage.cxx +++ b/pandatool/src/egg-palettize/textureImage.cxx @@ -530,6 +530,9 @@ copy_unplaced(bool redo_all) { } placement->set_dest(dest); + + } else { + placement->set_dest((DestTextureImage *)NULL); } } @@ -643,15 +646,17 @@ write_scale_info(ostream &out, int indent_level) { << " " << source->get_num_channels(); } - out << " new " << get_x_size() << " " << get_y_size() - << " " << get_num_channels(); + if (!_placement.empty()) { + out << " new " << get_x_size() << " " << get_y_size() + << " " << get_num_channels(); - if (source != (SourceTextureImage *)NULL && - source->is_size_known()) { - double scale = - 100.0 * (((double)get_x_size() / (double)source->get_x_size()) + - ((double)get_y_size() / (double)source->get_y_size())) / 2.0; - out << " scale " << scale << "%"; + if (source != (SourceTextureImage *)NULL && + source->is_size_known()) { + double scale = + 100.0 * (((double)get_x_size() / (double)source->get_x_size()) + + ((double)get_y_size() / (double)source->get_y_size())) / 2.0; + out << " scale " << scale << "%"; + } } out << "\n";