diff --git a/panda/src/egg2pg/eggLoader.cxx b/panda/src/egg2pg/eggLoader.cxx index 8379ddc2f1..b1ae9d2e1a 100644 --- a/panda/src/egg2pg/eggLoader.cxx +++ b/panda/src/egg2pg/eggLoader.cxx @@ -855,7 +855,7 @@ load_textures() { // Description: //////////////////////////////////////////////////////////////////// bool EggLoader:: -load_texture(TextureDef &def, const EggTexture *egg_tex) { +load_texture(TextureDef &def, EggTexture *egg_tex) { // Check to see if we should reduce the number of channels in // the texture. int wanted_channels = 0; @@ -951,6 +951,30 @@ load_texture(TextureDef &def, const EggTexture *egg_tex) { tex->set_alpha_filename(egg_tex->get_alpha_filename()); } + // See if there is some egg data hanging on the texture. In + // particular, the TxaFileFilter might have left that here for us. + TypedReferenceCount *aux = tex->get_aux_data("egg"); + if (aux != (TypedReferenceCount *)NULL && + aux->is_of_type(EggTexture::get_class_type())) { + EggTexture *aux_egg_tex = DCAST(EggTexture, aux); + + if (aux_egg_tex->get_alpha_mode() != EggTexture::AM_unspecified) { + egg_tex->set_alpha_mode(aux_egg_tex->get_alpha_mode()); + } + if (aux_egg_tex->get_format() != EggTexture::F_unspecified) { + egg_tex->set_format(aux_egg_tex->get_format()); + } + if (aux_egg_tex->get_minfilter() != EggTexture::FT_unspecified) { + egg_tex->set_minfilter(aux_egg_tex->get_minfilter()); + } + if (aux_egg_tex->get_magfilter() != EggTexture::FT_unspecified) { + egg_tex->set_magfilter(aux_egg_tex->get_magfilter()); + } + if (aux_egg_tex->has_anisotropic_degree()) { + egg_tex->set_anisotropic_degree(aux_egg_tex->get_anisotropic_degree()); + } + } + apply_texture_attributes(tex, egg_tex); // Make a texture stage for the texture. diff --git a/panda/src/egg2pg/eggLoader.h b/panda/src/egg2pg/eggLoader.h index 9c5d87375b..46b002d892 100644 --- a/panda/src/egg2pg/eggLoader.h +++ b/panda/src/egg2pg/eggLoader.h @@ -122,7 +122,7 @@ private: const LMatrix4d &mat); void load_textures(); - bool load_texture(TextureDef &def, const EggTexture *egg_tex); + bool load_texture(TextureDef &def, EggTexture *egg_tex); void apply_texture_attributes(Texture *tex, const EggTexture *egg_tex); Texture::CompressionMode convert_compression_mode(EggTexture::CompressionMode compression_mode) const; Texture::WrapMode convert_wrap_mode(EggTexture::WrapMode wrap_mode) const; diff --git a/panda/src/egg2pg/eggRenderState.cxx b/panda/src/egg2pg/eggRenderState.cxx index 1b9b65bf50..897aaf909d 100644 --- a/panda/src/egg2pg/eggRenderState.cxx +++ b/panda/src/egg2pg/eggRenderState.cxx @@ -60,6 +60,7 @@ fill_state(EggPrimitive *egg_prim) { EggRenderMode::DepthTestMode dtm = EggRenderMode::DTM_unspecified; EggRenderMode::VisibilityMode vm = EggRenderMode::VM_unspecified; bool implicit_alpha = false; + bool binary_alpha_only = true; // true if all alpha sources are binary alpha. bool has_draw_order = false; int draw_order = 0; bool has_bin = false; @@ -111,18 +112,26 @@ fill_state(EggPrimitive *egg_prim) { texture_attrib = texture_attrib->compose(def._texture); } - // If neither the primitive nor the texture specified an alpha - // mode, assume it should be alpha'ed if the texture has an - // alpha channel (unless the texture environment type is one - // that doesn't apply its alpha to the result). - if (egg_tex->affects_polygon_alpha() && - am == EggRenderMode::AM_unspecified) { + if (egg_tex->affects_polygon_alpha()) { const TextureAttrib *tex_attrib = DCAST(TextureAttrib, def._texture); Texture *tex = tex_attrib->get_texture(); nassertv(tex != (Texture *)NULL); - int num_components = tex->get_num_components(); - if (egg_tex->has_alpha_channel(num_components)) { - implicit_alpha = true; + + Texture::Format format = tex->get_format(); + if (Texture::has_alpha(format) && !Texture::has_binary_alpha(format)) { + // This texture specifies a gradient alpha format. + binary_alpha_only = false; + } + + if (am == EggRenderMode::AM_unspecified) { + // If neither the primitive nor the texture specified an + // alpha mode, assume it should be alpha'ed if the texture + // has an alpha channel (unless the texture environment type + // is one that doesn't apply its alpha to the result). + int num_components = tex->get_num_components(); + if (egg_tex->has_alpha_channel(num_components)) { + implicit_alpha = true; + } } } @@ -247,6 +256,7 @@ fill_state(EggPrimitive *egg_prim) { if (egg_prim->has_color()) { if (egg_prim->get_color()[3] != 1.0) { implicit_alpha = true; + binary_alpha_only = false; } } EggPrimitive::const_iterator vi; @@ -256,6 +266,7 @@ fill_state(EggPrimitive *egg_prim) { if ((*vi)->has_color()) { if ((*vi)->get_color()[3] != 1.0) { implicit_alpha = true; + binary_alpha_only = false; } } } @@ -265,10 +276,30 @@ fill_state(EggPrimitive *egg_prim) { } } - if (am == EggRenderMode::AM_on && - egg_alpha_mode != EggRenderMode::AM_unspecified) { + switch (am) { + case EggRenderMode::AM_on: // Alpha type "on" means to get the default transparency type. - am = egg_alpha_mode; + if (binary_alpha_only) { + am = EggRenderMode::AM_binary; + } else if (egg_alpha_mode != EggRenderMode::AM_unspecified) { + am = egg_alpha_mode; + } + break; + + case EggRenderMode::AM_blend: + case EggRenderMode::AM_ms: + case EggRenderMode::AM_ms_mask: + case EggRenderMode::AM_dual: + // Any of these modes gets implicitly downgraded to AM_binary, if + // all of the alpha sources only contribute a binary value to + // alpha. + if (binary_alpha_only) { + am = EggRenderMode::AM_binary; + } + break; + + default: + break; } switch (am) { diff --git a/panda/src/gobj/Sources.pp b/panda/src/gobj/Sources.pp index e701f8d0d7..0e2d655399 100644 --- a/panda/src/gobj/Sources.pp +++ b/panda/src/gobj/Sources.pp @@ -54,6 +54,7 @@ texture.I texture.h \ textureContext.I textureContext.h \ texturePool.I texturePool.h \ + texturePoolFilter.I texturePoolFilter.h \ textureStage.I textureStage.h \ transformBlend.I transformBlend.h \ transformBlendTable.I transformBlendTable.h \ @@ -107,6 +108,7 @@ shaderExpansion.cxx \ sliderTable.cxx \ texture.cxx textureContext.cxx texturePool.cxx \ + texturePoolFilter.cxx \ textureStage.cxx \ transformBlend.cxx \ transformBlendTable.cxx \ @@ -164,6 +166,7 @@ texture.I texture.h \ textureContext.I textureContext.h \ texturePool.I texturePool.h \ + texturePoolFilter.I texturePoolFilter.h \ textureStage.I textureStage.h \ transformBlend.I transformBlend.h \ transformBlendTable.I transformBlendTable.h \ diff --git a/panda/src/gobj/config_gobj.cxx b/panda/src/gobj/config_gobj.cxx index 489f1dca08..16e187d9e6 100644 --- a/panda/src/gobj/config_gobj.cxx +++ b/panda/src/gobj/config_gobj.cxx @@ -41,6 +41,7 @@ #include "queryContext.h" #include "sliderTable.h" #include "texture.h" +#include "texturePoolFilter.h" #include "textureStage.h" #include "textureContext.h" #include "shaderExpansion.h" @@ -248,60 +249,62 @@ ConfigVariableDouble default_keystone ConfigureFn(config_gobj) { BufferContext::init_type(); Geom::init_type(); - GeomMunger::init_type(); - GeomPrimitive::init_type(); - GeomTriangles::init_type(); - GeomTristrips::init_type(); - GeomTrifans::init_type(); + GeomContext::init_type(); GeomLines::init_type(); GeomLinestrips::init_type(); + GeomMunger::init_type(); GeomPoints::init_type(); + GeomPrimitive::init_type(); + GeomTriangles::init_type(); + GeomTrifans::init_type(); + GeomTristrips::init_type(); GeomVertexArrayData::init_type(); GeomVertexArrayFormat::init_type(); GeomVertexData::init_type(); GeomVertexFormat::init_type(); - TextureContext::init_type(); - GeomContext::init_type(); - VertexBufferContext::init_type(); IndexBufferContext::init_type(); + InternalName::init_type(); + Lens::init_type(); Material::init_type(); + MatrixLens::init_type(); OcclusionQueryContext::init_type(); OrthographicLens::init_type(); - MatrixLens::init_type(); PerspectiveLens::init_type(); - Lens::init_type(); QueryContext::init_type(); + ShaderContext::init_type(); + ShaderExpansion::init_type(); SliderTable::init_type(); Texture::init_type(); + TextureContext::init_type(); + TexturePoolFilter::init_type(); TextureStage::init_type(); - ShaderExpansion::init_type(); - ShaderContext::init_type(); TransformBlend::init_type(); TransformBlendTable::init_type(); TransformTable::init_type(); UserVertexSlider::init_type(); UserVertexTransform::init_type(); - VertexTransform::init_type(); + VertexBufferContext::init_type(); VertexSlider::init_type(); + VertexTransform::init_type(); VideoTexture::init_type(); - InternalName::init_type(); //Registration of writeable object's creation //functions with BamReader's factory Geom::register_with_read_factory(); - GeomTriangles::register_with_read_factory(); - GeomTristrips::register_with_read_factory(); - GeomTrifans::register_with_read_factory(); GeomLines::register_with_read_factory(); GeomLinestrips::register_with_read_factory(); GeomPoints::register_with_read_factory(); + GeomTriangles::register_with_read_factory(); + GeomTrifans::register_with_read_factory(); + GeomTristrips::register_with_read_factory(); GeomVertexArrayData::register_with_read_factory(); GeomVertexArrayFormat::register_with_read_factory(); GeomVertexData::register_with_read_factory(); GeomVertexFormat::register_with_read_factory(); + InternalName::register_with_read_factory(); Material::register_with_read_factory(); - OrthographicLens::register_with_read_factory(); MatrixLens::register_with_read_factory(); + OrthographicLens::register_with_read_factory(); PerspectiveLens::register_with_read_factory(); SliderTable::register_with_read_factory(); Texture::register_with_read_factory(); @@ -310,7 +313,6 @@ ConfigureFn(config_gobj) { TransformTable::register_with_read_factory(); UserVertexSlider::register_with_read_factory(); UserVertexTransform::register_with_read_factory(); - InternalName::register_with_read_factory(); } ostream & diff --git a/panda/src/gobj/gobj_composite2.cxx b/panda/src/gobj/gobj_composite2.cxx index 901fee2bda..c4cf2bf874 100644 --- a/panda/src/gobj/gobj_composite2.cxx +++ b/panda/src/gobj/gobj_composite2.cxx @@ -15,6 +15,7 @@ #include "texture.cxx" #include "textureContext.cxx" #include "texturePool.cxx" +#include "texturePoolFilter.cxx" #include "textureStage.cxx" #include "shaderExpansion.cxx" #include "shaderContext.cxx" diff --git a/panda/src/gobj/texture.cxx b/panda/src/gobj/texture.cxx index 8397e9c10e..410555a1cd 100644 --- a/panda/src/gobj/texture.cxx +++ b/panda/src/gobj/texture.cxx @@ -415,6 +415,50 @@ estimate_texture_memory() const { return bytes; } +//////////////////////////////////////////////////////////////////// +// Function: Texture::set_aux_data +// Access: Published +// Description: Records an arbitrary object in the Texture, +// associated with a specified key. The object may +// later be retrieved by calling get_aux_data() with the +// same key. +// +// These data objects are not recorded to a bam or txo +// file. +//////////////////////////////////////////////////////////////////// +void Texture:: +set_aux_data(const string &key, TypedReferenceCount *aux_data) { + _aux_data[key] = aux_data; +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::clear_aux_data +// Access: Published +// Description: Removes a record previously recorded via +// set_aux_data(). +//////////////////////////////////////////////////////////////////// +void Texture:: +clear_aux_data(const string &key) { + _aux_data.erase(key); +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::get_aux_data +// Access: Published +// Description: Returns a record previously recorded via +// set_aux_data(). Returns NULL if there was no record +// associated with the indicated key. +//////////////////////////////////////////////////////////////////// +TypedReferenceCount *Texture:: +get_aux_data(const string &key) const { + AuxData::const_iterator di; + di = _aux_data.find(key); + if (di != _aux_data.end()) { + return (*di).second; + } + return NULL; +} + //////////////////////////////////////////////////////////////////// // Function: Texture::read_txo // Access: Published @@ -2357,6 +2401,23 @@ has_alpha(Format format) { } } +//////////////////////////////////////////////////////////////////// +// Function: Texture::has_binary_alpha +// Access: Public, Static +// Description: Returns true if the indicated format includes a +// binary alpha only, false otherwise. +//////////////////////////////////////////////////////////////////// +bool Texture:: +has_binary_alpha(Format format) { + switch (format) { + case F_rgbm: + return true; + + default: + return false; + } +} + //////////////////////////////////////////////////////////////////// // Function: Texture::reconsider_z_size // Access: Protected diff --git a/panda/src/gobj/texture.h b/panda/src/gobj/texture.h index b4a06d750c..991bf2ff57 100644 --- a/panda/src/gobj/texture.h +++ b/panda/src/gobj/texture.h @@ -311,6 +311,10 @@ PUBLISHED: size_t estimate_texture_memory() const; + void set_aux_data(const string &key, TypedReferenceCount *aux_data); + void clear_aux_data(const string &key); + TypedReferenceCount *get_aux_data(const string &key) const; + PUBLISHED: // These are published, but in general, you shouldn't be mucking // with these values; they are set automatically when a texture is @@ -360,6 +364,7 @@ public: static bool is_specific(CompressionMode compression); static bool has_alpha(Format format); + static bool has_binary_alpha(Format format); protected: virtual bool do_read(const Filename &fullpath, const Filename &alpha_fullpath, @@ -516,6 +521,11 @@ protected: UpdateSeq _modified; +private: + // The auxiliary data is not recorded to a bam file. + typedef pmap AuxData; + AuxData _aux_data; + // Datagram stuff public: static void register_with_read_factory(); diff --git a/panda/src/gobj/texturePool.cxx b/panda/src/gobj/texturePool.cxx index ccb56e1bec..8513fc20a9 100644 --- a/panda/src/gobj/texturePool.cxx +++ b/panda/src/gobj/texturePool.cxx @@ -25,10 +25,11 @@ #include "bamCache.h" #include "bamCacheRecord.h" #include "pnmFileTypeRegistry.h" +#include "texturePoolFilter.h" +#include "configVariableList.h" +#include "load_dso.h" - -TexturePool *TexturePool::_global_ptr = (TexturePool *)NULL; - +TexturePool *TexturePool::_global_ptr; //////////////////////////////////////////////////////////////////// // Function: TexturePool::write @@ -62,6 +63,19 @@ register_texture_type(MakeTextureFunc *func, const string &extensions) { } } +//////////////////////////////////////////////////////////////////// +// Function: TexturePool::register_filter +// Access: Public +// Description: Records a TexturePoolFilter object that may operate +// on texture images as they are loaded from disk. +//////////////////////////////////////////////////////////////////// +void TexturePool:: +register_filter(TexturePoolFilter *filter) { + gobj_cat.info() + << "Registering Texture filter " << *filter << "\n"; + _filter_registry.push_back(filter); +} + //////////////////////////////////////////////////////////////////// // Function: TexturePool::get_texture_type // Access: Public @@ -152,6 +166,11 @@ TexturePool *TexturePool:: get_global_ptr() { if (_global_ptr == (TexturePool *)NULL) { _global_ptr = new TexturePool; + + // We have to call this here, not in the constructor, so that the + // _global_ptr is safely assigned by the time the filters begin to + // load. + _global_ptr->load_filters(); } return _global_ptr; } @@ -229,20 +248,27 @@ ns_load_texture(const Filename &orig_filename, int primary_file_num_channels, return tex; } + // The texture was not found in the pool. PT(Texture) tex; PT(BamCacheRecord) record; bool store_record = false; + // Can one of our texture filters supply the texture? + tex = pre_load(orig_filename, Filename(), primary_file_num_channels, 0, + read_mipmaps); + BamCache *cache = BamCache::get_global_ptr(); - if (cache->get_active() && !textures_header_only) { - // See if the texture can be found in the on-disk cache, if it is - // active. - record = cache->lookup(filename, "txo"); - if (record != (BamCacheRecord *)NULL) { - if (record->has_data()) { - gobj_cat.info() - << "Texture " << filename << " found in disk cache.\n"; - tex = DCAST(Texture, record->extract_data()); + if (tex == (Texture *)NULL) { + // The texture was not supplied by a texture filter. See if it + // can be found in the on-disk cache, if it is active. + if (cache->get_active() && !textures_header_only) { + record = cache->lookup(filename, "txo"); + if (record != (BamCacheRecord *)NULL) { + if (record->has_data()) { + gobj_cat.info() + << "Texture " << filename << " found in disk cache.\n"; + tex = DCAST(Texture, record->extract_data()); + } } } } @@ -276,6 +302,10 @@ ns_load_texture(const Filename &orig_filename, int primary_file_num_channels, } nassertr(!tex->get_fullpath().empty(), tex); + + // Finally, apply any post-loading texture filters. + tex = post_load(tex); + return tex; } @@ -318,16 +348,24 @@ ns_load_texture(const Filename &orig_filename, PT(BamCacheRecord) record; bool store_record = false; + // Can one of our texture filters supply the texture? + tex = pre_load(orig_filename, alpha_filename, primary_file_num_channels, + alpha_file_channel, read_mipmaps); + BamCache *cache = BamCache::get_global_ptr(); - if (cache->get_active() && !textures_header_only) { - // See if the texture can be found in the on-disk cache, if it is - // active. - record = cache->lookup(filename, "txo"); - if (record != (BamCacheRecord *)NULL) { - if (record->has_data()) { - gobj_cat.info() - << "Texture " << filename << " found in disk cache.\n"; - tex = DCAST(Texture, record->extract_data()); + if (tex == (Texture *)NULL) { + // The texture was not supplied by a texture filter. See if it + // can be found in the on-disk cache, if it is active. + if (cache->get_active() && !textures_header_only) { + // See if the texture can be found in the on-disk cache, if it is + // active. + record = cache->lookup(filename, "txo"); + if (record != (BamCacheRecord *)NULL) { + if (record->has_data()) { + gobj_cat.info() + << "Texture " << filename << " found in disk cache.\n"; + tex = DCAST(Texture, record->extract_data()); + } } } } @@ -364,6 +402,10 @@ ns_load_texture(const Filename &orig_filename, } nassertr(!tex->get_fullpath().empty(), tex); + + // Finally, apply any post-loading texture filters. + tex = post_load(tex); + return tex; } @@ -684,3 +726,82 @@ report_texture_unreadable(const Filename &filename) const { } } } + +//////////////////////////////////////////////////////////////////// +// Function: TexturePool::pre_load +// Access: Private +// Description: Invokes pre_load() on all registered filters until +// one returns non-NULL; returns NULL if there are no +// registered filters or if all registered filters +// returned NULL. +//////////////////////////////////////////////////////////////////// +PT(Texture) TexturePool:: +pre_load(const Filename &orig_filename, const Filename &orig_alpha_filename, + int primary_file_num_channels, int alpha_file_channel, + bool read_mipmaps) { + PT(Texture) tex; + + FilterRegistry::iterator fi; + for (fi = _filter_registry.begin(); + fi != _filter_registry.end(); + ++fi) { + tex = (*fi)->pre_load(orig_filename, orig_alpha_filename, + primary_file_num_channels, alpha_file_channel, + read_mipmaps); + if (tex != (Texture *)NULL) { + return tex; + } + } + + return tex; +} + +//////////////////////////////////////////////////////////////////// +// Function: TexturePool::post_load +// Access: Public, Virtual +// Description: Invokes post_load() on all registered filters. +//////////////////////////////////////////////////////////////////// +PT(Texture) TexturePool:: +post_load(Texture *tex) { + PT(Texture) result = tex; + + FilterRegistry::iterator fi; + for (fi = _filter_registry.begin(); + fi != _filter_registry.end(); + ++fi) { + result = (*fi)->post_load(result); + } + + return result; +} + + +//////////////////////////////////////////////////////////////////// +// Function: TexturePool::load_filters +// Access: Private +// Description: Loads up all of the dll's named by the texture-filter +// Config.prc variable. +//////////////////////////////////////////////////////////////////// +void TexturePool:: +load_filters() { + ConfigVariableList texture_filter + ("texture-filter", + PRC_DESC("Names one or more external libraries that should be loaded for the " + "purposes of performing texture filtering. This variable may be repeated several " + "times. As in load-display, the actual library filename is derived by " + "prefixing 'lib' to the specified name.")); + + int num_aux = texture_filter.get_num_unique_values(); + for (int i = 0; i < num_aux; i++) { + string name = texture_filter.get_unique_value(i); + + Filename dlname = Filename::dso_filename("lib" + name + ".so"); + gobj_cat.info() + << "loading texture filter: " << dlname.to_os_specific() << endl; + void *tmp = load_dso(dlname); + if (tmp == (void *)NULL) { + gobj_cat.info() + << "Unable to load: " << load_dso_error() << endl; + } + } +} diff --git a/panda/src/gobj/texturePool.h b/panda/src/gobj/texturePool.h index fd6f71bcfc..c7ec4883af 100644 --- a/panda/src/gobj/texturePool.h +++ b/panda/src/gobj/texturePool.h @@ -26,6 +26,8 @@ #include "pmap.h" +class TexturePoolFilter; + //////////////////////////////////////////////////////////////////// // Class : TexturePool // Description : This is the preferred interface for loading textures @@ -68,12 +70,13 @@ PUBLISHED: INLINE static void clear_fake_texture_image(); INLINE static bool has_fake_texture_image(); INLINE static const string &get_fake_texture_image(); - + static void write(ostream &out); public: typedef PT(Texture) MakeTextureFunc(); void register_texture_type(MakeTextureFunc *func, const string &extensions); + void register_filter(TexturePoolFilter *filter); MakeTextureFunc *get_texture_type(const string &extension) const; PT(Texture) make_texture(const string &extension) const; @@ -107,6 +110,16 @@ private: void report_texture_unreadable(const Filename &filename) const; + // Methods to invoke a TexturePoolFilter. + PT(Texture) pre_load(const Filename &orig_filename, + const Filename &orig_alpha_filename, + int primary_file_num_channels, + int alpha_file_channel, + bool read_mipmaps); + PT(Texture) post_load(Texture *tex); + + void load_filters(); + static TexturePool *_global_ptr; typedef phash_map Textures; Textures _textures; @@ -116,6 +129,9 @@ private: typedef pmap TypeRegistry; TypeRegistry _type_registry; + + typedef pvector FilterRegistry; + FilterRegistry _filter_registry; }; #include "texturePool.I" diff --git a/panda/src/gobj/texturePoolFilter.I b/panda/src/gobj/texturePoolFilter.I new file mode 100644 index 0000000000..dce4397c38 --- /dev/null +++ b/panda/src/gobj/texturePoolFilter.I @@ -0,0 +1,18 @@ +// Filename: texturePoolFilter.I +// Created by: drose (27Jul06) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + diff --git a/panda/src/gobj/texturePoolFilter.cxx b/panda/src/gobj/texturePoolFilter.cxx new file mode 100644 index 0000000000..43e9adc1ec --- /dev/null +++ b/panda/src/gobj/texturePoolFilter.cxx @@ -0,0 +1,72 @@ +// Filename: texturePoolFilter.cxx +// Created by: drose (27Jul06) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#include "texturePoolFilter.h" + +TypeHandle TexturePoolFilter::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: TexturePoolFilter::Destructor +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +TexturePoolFilter:: +~TexturePoolFilter() { +} + +//////////////////////////////////////////////////////////////////// +// Function: TexturePoolFilter::pre_load +// Access: Public, Virtual +// Description: This method is called before each texture is loaded +// from disk, via the TexturePool, for the first time. +// If this method returns NULL, then a new Texture will +// be allocated and loaded from disk normally by the +// TexturePool; otherwise, if it returns non-NULL, then +// that returned pointer will be used as the Texture for +// this filename. +//////////////////////////////////////////////////////////////////// +PT(Texture) TexturePoolFilter:: +pre_load(const Filename &, const Filename &, int, int, bool) { + return NULL; +} + +//////////////////////////////////////////////////////////////////// +// Function: TexturePoolFilter::post_load +// Access: Public, Virtual +// Description: This method is called after each texture has been +// loaded from disk, via the TexturePool, for the first +// time. By the time this method is called, the Texture +// has already been fully read from disk. This method +// should return the Texture pointer that the +// TexturePool should actually return (usually it is the +// same as the pointer supplied). +//////////////////////////////////////////////////////////////////// +PT(Texture) TexturePoolFilter:: +post_load(Texture *tex) { + return tex; +} + +//////////////////////////////////////////////////////////////////// +// Function: TexturePoolFilter::output +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void TexturePoolFilter:: +output(ostream &out) const { + out << get_type(); +} diff --git a/panda/src/gobj/texturePoolFilter.h b/panda/src/gobj/texturePoolFilter.h new file mode 100644 index 0000000000..ebf17b2df3 --- /dev/null +++ b/panda/src/gobj/texturePoolFilter.h @@ -0,0 +1,87 @@ +// Filename: texturePoolFilter.h +// Created by: drose (27Jul06) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#ifndef TEXTUREPOOLFILTER_H +#define TEXTUREPOOLFILTER_H + +#include "pandabase.h" +#include "texture.h" +#include "pointerTo.h" +#include "typedObject.h" + +//////////////////////////////////////////////////////////////////// +// Class : TexturePoolFilter +// Description : This is an abstract base class, a placeholder for any +// number of different classes that may wish to +// implement an effect on every texture loaded from disk +// via the TexturePool. +// +// In practice, as of the time of this writing, only the +// TxaFileFilter (in pandatool) actually implements +// this. But other kinds of filters are possible. +// +// This filter, once registered, will get a callback and +// a chance to modify each texture as it is loaded from +// disk the first time. If more than one filter is +// registered, each will be called in sequence, in the +// order in which they were registered. +// +// The filter does not get called again if the texture +// is subsequently reloaded from disk. It is suggested +// that filters for which this might be a problem should +// call tex->set_keep_ram_image(true). +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA TexturePoolFilter : public TypedObject { +public: + virtual ~TexturePoolFilter(); + + virtual PT(Texture) pre_load(const Filename &orig_filename, + const Filename &orig_alpha_filename, + int primary_file_num_channels, + int alpha_file_channel, + bool read_mipmaps); + virtual PT(Texture) post_load(Texture *tex); + + virtual void output(ostream &out) const; + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + TypedObject::init_type(); + register_type(_type_handle, "TexturePoolFilter", + TypedObject::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; +}; + +INLINE ostream &operator << (ostream &out, const TexturePoolFilter &filter) { + filter.output(out); + return out; +} + +#include "texturePoolFilter.I" + +#endif diff --git a/pandatool/src/egg-palettize/Sources.pp b/pandatool/src/egg-palettize/Sources.pp index 4a8993e056..b2492cbb4b 100644 --- a/pandatool/src/egg-palettize/Sources.pp +++ b/pandatool/src/egg-palettize/Sources.pp @@ -15,3 +15,13 @@ #end bin_target +#begin lib_target + #define TARGET txafile + #define LOCAL_LIBS \ + palettizer + + #define SOURCES \ + txaFileFilter.h txaFileFilter.I txaFileFilter.cxx + +#end lib_target + diff --git a/pandatool/src/egg-palettize/txaFileFilter.I b/pandatool/src/egg-palettize/txaFileFilter.I new file mode 100644 index 0000000000..323d8b30bc --- /dev/null +++ b/pandatool/src/egg-palettize/txaFileFilter.I @@ -0,0 +1,18 @@ +// Filename: txaFileFilter.I +// Created by: drose (27Jul06) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + diff --git a/pandatool/src/egg-palettize/txaFileFilter.cxx b/pandatool/src/egg-palettize/txaFileFilter.cxx new file mode 100644 index 0000000000..6d0f05120f --- /dev/null +++ b/pandatool/src/egg-palettize/txaFileFilter.cxx @@ -0,0 +1,162 @@ +// Filename: txaFileFilter.cxx +// Created by: drose (27Jul06) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#include "txaFileFilter.h" +#include "palettizer.h" +#include "txaFile.h" +#include "textureImage.h" +#include "sourceTextureImage.h" +#include "texturePool.h" +#include "dconfig.h" +#include "configVariableFilename.h" +#include "virtualFileSystem.h" +#include "config_util.h" + +NotifyCategoryDeclNoExport(txafile); +NotifyCategoryDef(txafile, ""); + +// A few lines to register this filter type with the TexturePool when +// the shared library is loaded. +Configure(config_txaFileFilter); +ConfigureFn(config_txaFileFilter) { + TxaFileFilter::init_type(); + TexturePool *pool = TexturePool::get_global_ptr(); + pool->register_filter(new TxaFileFilter); +} + +TypeHandle TxaFileFilter::_type_handle; +TxaFile *TxaFileFilter::_txa_file; +bool TxaFileFilter::_got_txa_file; + +//////////////////////////////////////////////////////////////////// +// Function: TxaFileFilter::post_load +// Access: Public, Virtual +// Description: This method is called after each texture has been +// loaded from disk, via the TexturePool, for the first +// time. By the time this method is called, the Texture +// has already been fully read from disk. This method +// should return the Texture pointer that the +// TexturePool should actually return (usually it is the +// same as the pointer supplied). +//////////////////////////////////////////////////////////////////// +PT(Texture) TxaFileFilter:: +post_load(Texture *tex) { + if (!_got_txa_file) { + read_txa_file(); + } + + TextureImage tex_image; + string name = tex->get_filename().get_basename_wo_extension(); + tex_image.set_name(name); + + SourceTextureImage *source = tex_image.get_source + (tex->get_fullpath(), tex->get_alpha_fullpath(), 0); + PNMImage pnm_image; + tex->store(pnm_image); + source->set_header(pnm_image); + tex_image.set_source_image(pnm_image); + + tex_image.pre_txa_file(); + + bool matched = _txa_file->match_texture(&tex_image); + if (txafile_cat.is_debug()) { + if (!matched) { + txafile_cat.debug() + << "Not matched: " << name << "\n"; + } else { + txafile_cat.debug() + << "Matched: " << name << "\n"; + } + } + + tex_image.post_txa_file(); + + PNMImage dest(tex_image.get_x_size(), + tex_image.get_y_size(), + tex_image.get_num_channels(), + pnm_image.get_maxval()); + dest.quick_filter_from(pnm_image); + + tex->load(dest); + + // Create an EggTexture to pass back the requested alpha mode to + // the egg loader, if the texture is now being loaded from an egg + // file. + PT(EggTexture) egg_tex = new EggTexture(tex->get_name(), tex->get_fullpath()); + const TextureProperties &props = tex_image.get_properties(); + + egg_tex->set_alpha_mode(tex_image.get_alpha_mode()); + egg_tex->set_format(props._format); + egg_tex->set_minfilter(props._minfilter); + egg_tex->set_minfilter(props._magfilter); + egg_tex->set_anisotropic_degree(props._anisotropic_degree); + + tex->set_aux_data("egg", egg_tex); + + return tex; +} + +//////////////////////////////////////////////////////////////////// +// Function: TxaFileFilter::read_txa_file +// Access: Private, Static +// Description: Reads the textures.txa file named by the variable +// txa-file. Called only once, at startup. +//////////////////////////////////////////////////////////////////// +void TxaFileFilter:: +read_txa_file() { + VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); + + // We need to create a global Palettizer object to hold some of the + // global properties that may be specified in a txa file. + if (pal == (Palettizer *)NULL) { + pal = new Palettizer; + } + + _txa_file = new TxaFile; + _got_txa_file = true; + + ConfigVariableFilename txa_file + ("txa-file", Filename("textures.txa"), + PRC_DESC("Specify the name of the txa file to load when the txafile texture filter" + "is in effect.")); + + Filename filename = txa_file; + vfs->resolve_filename(filename, texture_path); + vfs->resolve_filename(filename, model_path); + + if (!vfs->exists(filename)) { + txafile_cat.warning() + << "Filename " << filename << " not found.\n"; + } else { + filename.set_text(); + istream *ifile = vfs->open_read_file(filename, true); + if (ifile == (istream *)NULL) { + txafile_cat.warning() + << "Filename " << filename << " cannot be read.\n"; + } else { + if (!_txa_file->read(*ifile, filename)) { + txafile_cat.warning() + << "Syntax errors in " << filename << "\n"; + } else { + txafile_cat.info() + << "Read " << filename << "\n"; + } + vfs->close_read_file(ifile); + } + } +} diff --git a/pandatool/src/egg-palettize/txaFileFilter.h b/pandatool/src/egg-palettize/txaFileFilter.h new file mode 100644 index 0000000000..6163af1616 --- /dev/null +++ b/pandatool/src/egg-palettize/txaFileFilter.h @@ -0,0 +1,80 @@ +// Filename: txaFileFilter.h +// Created by: drose (27Jul06) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#ifndef TXAFILEFILTER_H +#define TXAFILEFILTER_H + +#include "pandatoolbase.h" +#include "texturePoolFilter.h" + +class TxaFile; + +//////////////////////////////////////////////////////////////////// +// Class : TxaFileFilter +// Description : This is an abstract base class, a placeholder for any +// number of different classes that may wish to +// implement an effect on every texture loaded from disk +// via the TexturePool. +// +// In practice, as of the time of this writing, only the +// TxaFileFilter (in pandatool) actually implements +// this. But other kinds of filters are possible. +// +// This filter, once registered, will get a callback and +// a chance to modify each texture as it is loaded from +// disk the first time. If more than one filter is +// registered, each will be called in sequence, in the +// order in which they were registered. +// +// The filter does not get called again if the texture +// is subsequently reloaded from disk. It is suggested +// that filters for which this might be a problem should +// call tex->set_keep_ram_image(true). +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA TxaFileFilter : public TexturePoolFilter { +public: + virtual PT(Texture) post_load(Texture *tex); + +private: + static void read_txa_file(); + +private: + static TxaFile *_txa_file; + static bool _got_txa_file; + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + TexturePoolFilter::init_type(); + register_type(_type_handle, "TxaFileFilter", + TexturePoolFilter::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; +}; + +#include "txaFileFilter.I" + +#endif