Răsfoiți Sursa

more robust texture/alpha combinations

David Rose 23 ani în urmă
părinte
comite
28743b123b

+ 3 - 3
panda/src/egg/eggTexture.I

@@ -276,11 +276,11 @@ has_transform() const {
 ////////////////////////////////////////////////////////////////////
 //     Function: EggTexture::get_transform
 //       Access: Public
-//  Description:
+//  Description: Returns the texture matrix transform if one has been
+//               specified, or identity matrix otherwise.
 ////////////////////////////////////////////////////////////////////
-INLINE LMatrix3d EggTexture::
+INLINE const LMatrix3d &EggTexture::
 get_transform() const {
-  nassertr(has_transform(), LMatrix3d::ident_mat());
   return _transform;
 }
 

+ 7 - 7
panda/src/egg/eggTexture.cxx

@@ -94,6 +94,13 @@ write(ostream &out, int indent_level) const {
   write_header(out, indent_level, "<Texture>");
   enquote_string(out, get_filename(), indent_level + 2) << "\n";
 
+  if (has_alpha_filename()) {
+    indent(out, indent_level + 2)
+      << "<Scalar> alpha-file { ";
+    enquote_string(out, get_alpha_filename());
+    out << " }\n";
+  }
+
   if (get_format() != F_unspecified) {
     indent(out, indent_level + 2)
       << "<Scalar> format { " << get_format() << " }\n";
@@ -134,13 +141,6 @@ write(ostream &out, int indent_level) const {
       << "<Scalar> envtype { " << get_env_type() << " }\n";
   }
 
-  if (has_alpha_filename()) {
-    indent(out, indent_level + 2)
-      << "<Scalar> alpha-file { ";
-    enquote_string(out, get_alpha_filename());
-    out << " }\n";
-  }
-
   EggRenderMode::write(out, indent_level + 2);
 
   if (has_transform()) {

+ 1 - 1
panda/src/egg/eggTexture.h

@@ -117,7 +117,7 @@ public:
   INLINE void set_transform(const LMatrix3d &transform);
   INLINE void clear_transform();
   INLINE bool has_transform() const;
-  INLINE LMatrix3d get_transform() const;
+  INLINE const LMatrix3d &get_transform() const;
   INLINE bool transform_is_identity() const;
 
   INLINE void set_alpha_filename(const Filename &filename);

+ 45 - 5
panda/src/egg2pg/eggLoader.cxx

@@ -476,20 +476,60 @@ load_textures() {
 ////////////////////////////////////////////////////////////////////
 bool EggLoader::
 load_texture(TextureDef &def, const EggTexture *egg_tex) {
+  // Check to see if we should reduce the number of components in
+  // the texture.
+  int wanted_components = 0;
+  switch (egg_tex->get_format()) {
+  case EggTexture::F_red:
+  case EggTexture::F_green:
+  case EggTexture::F_blue:
+  case EggTexture::F_alpha:
+  case EggTexture::F_luminance:
+    wanted_components = 1;
+    break;
+
+  case EggTexture::F_luminance_alpha:
+  case EggTexture::F_luminance_alphamask:
+    wanted_components = 2;
+    break;
+
+  case EggTexture::F_rgb:
+  case EggTexture::F_rgb12:
+  case EggTexture::F_rgb8:
+  case EggTexture::F_rgb5:
+  case EggTexture::F_rgb332:
+    wanted_components = 3;
+    break;
+
+  case EggTexture::F_rgba:
+  case EggTexture::F_rgbm:
+  case EggTexture::F_rgba12:
+  case EggTexture::F_rgba8:
+  case EggTexture::F_rgba4:
+  case EggTexture::F_rgba5:
+    wanted_components = 4;
+    break;
+
+  case EggTexture::F_unspecified:
+    break;
+  }
+
   Texture *tex;
   if (egg_tex->has_alpha_filename()) {
     tex = TexturePool::load_texture(egg_tex->get_fullpath(),
-                                    egg_tex->get_alpha_fullpath());
+                                    egg_tex->get_alpha_fullpath(),
+                                    wanted_components);
   } else {
-    tex = TexturePool::load_texture(egg_tex->get_fullpath());
+    tex = TexturePool::load_texture(egg_tex->get_fullpath(),
+                                    wanted_components);
   }
   if (tex == (Texture *)NULL) {
     return false;
   }
 
-  // Record the original original filenames in the textures (as loaded
-  // from the egg file).  These filenames will be written back to the
-  // bam file if the bam file is written out.
+  // Record the original filenames in the textures (as loaded from the
+  // egg file).  These filenames will be written back to the bam file
+  // if the bam file is written out.
   tex->set_filename(egg_tex->get_filename());
   if (egg_tex->has_alpha_filename()) {
     tex->set_alpha_filename(egg_tex->get_alpha_filename());

+ 58 - 28
panda/src/gobj/texture.cxx

@@ -16,9 +16,6 @@
 //
 ////////////////////////////////////////////////////////////////////
 
-////////////////////////////////////////////////////////////////////
-// Includes
-////////////////////////////////////////////////////////////////////
 #include "pandabase.h"
 #include "texture.h"
 #include "config_gobj.h"
@@ -33,12 +30,8 @@
 #include <stddef.h>
 
 
-////////////////////////////////////////////////////////////////////
-// Static variables
-////////////////////////////////////////////////////////////////////
 TypeHandle Texture::_type_handle;
 
-
 ////////////////////////////////////////////////////////////////////
 //     Function: up_to_power_2
 //  Description: Returns the smallest power of 2 greater than or equal
@@ -110,6 +103,28 @@ consider_rescale(PNMImage &pnmimage, const string &name) {
   }
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: consider_downgrade
+//  Description: Reduces the number of channels in the texture, if
+//               necessary, according to num_components.
+////////////////////////////////////////////////////////////////////
+static void
+consider_downgrade(PNMImage &pnmimage, int num_components, 
+                   const string &name) {
+  if (num_components != 0 && num_components < pnmimage.get_num_channels()) {
+    // One special case: we can't reduce from 3 to 2 components, since
+    // that would require adding an alpha channel.
+    if (pnmimage.get_num_channels() == 3 && num_components == 2) {
+      return;
+    }
+
+    gobj_cat.info()
+      << "Downgrading " << name << " from " << pnmimage.get_num_channels()
+      << " components to " << num_components << ".\n";
+    pnmimage.set_num_channels(num_components);
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: Constructor
 //       Access: Published
@@ -163,10 +178,13 @@ Texture::
 ////////////////////////////////////////////////////////////////////
 //     Function: read
 //       Access: Published
-//  Description: Reads the texture from the indicated filename.
+//  Description: Reads the texture from the indicated filename.  If
+//               num_components is not 0, it specifies the number of
+//               components to downgrade the image to if it is greater
+//               than this number.
 ////////////////////////////////////////////////////////////////////
 bool Texture::
-read(const Filename &fullpath) {
+read(const Filename &fullpath, int num_components) {
   PNMImage image;
 
   if (!image.read(fullpath)) {
@@ -188,7 +206,7 @@ read(const Filename &fullpath) {
 
   // Check to see if we need to scale it.
   consider_rescale(image, get_name());
-
+  consider_downgrade(image, num_components, get_name());
   return load(image);
 }
 
@@ -199,7 +217,8 @@ read(const Filename &fullpath) {
 //               to get a 4-component image
 ////////////////////////////////////////////////////////////////////
 bool Texture::
-read(const Filename &fullpath, const Filename &alpha_fullpath) {
+read(const Filename &fullpath, const Filename &alpha_fullpath,
+     int num_components) {
   PNMImage image;
   if (!image.read(fullpath)) {
     gobj_cat.error()
@@ -244,22 +263,16 @@ read(const Filename &fullpath, const Filename &alpha_fullpath) {
     alpha_image = scaled;
   }
 
-  // Make the original image a 4-component image
+  // Make the original image a 4-component image by taking the
+  // grayscale value from the second image.
   image.add_alpha();
-  if (alpha_image.has_alpha()) {
-    for (int x = 0; x < image.get_x_size(); x++) {
-      for (int y = 0; y < image.get_y_size(); y++) {
-        image.set_alpha(x, y, alpha_image.get_alpha(x, y));
-      }
-    }
-  } else {
-    for (int x = 0; x < image.get_x_size(); x++) {
-      for (int y = 0; y < image.get_y_size(); y++) {
-        image.set_alpha(x, y, alpha_image.get_gray(x, y));
-      }
+  for (int x = 0; x < image.get_x_size(); x++) {
+    for (int y = 0; y < image.get_y_size(); y++) {
+      image.set_alpha(x, y, alpha_image.get_gray(x, y));
     }
   }
 
+  consider_downgrade(image, num_components, get_name());
   return load(image);
 }
 
@@ -687,10 +700,17 @@ make_Texture(const FactoryParams &params) {
   string name;
   Filename filename, alpha_filename;
 
+  // Get the properties written by ImageBuffer::write_datagram().
   name = scan.get_string();
   filename = scan.get_string();
   alpha_filename = scan.get_string();
 
+  // Get the expected number of components.
+  int num_components = 0;
+  if (manager->get_file_minor_ver() >= 2) {
+    num_components = scan.get_uint8();
+  }
+
   PT(Texture) me;
 
   if (filename.empty()) {
@@ -702,9 +722,9 @@ make_Texture(const FactoryParams &params) {
   } else {
     // This texture does have a filename, so try to load it from disk.
     if (alpha_filename.empty()) {
-      me = TexturePool::load_texture(filename);
+      me = TexturePool::load_texture(filename, num_components);
     } else {
-      me = TexturePool::load_texture(filename, alpha_filename);
+      me = TexturePool::load_texture(filename, alpha_filename, num_components);
     }
   }
 
@@ -774,19 +794,29 @@ fillin(DatagramIterator &scan, BamReader *manager) {
 ////////////////////////////////////////////////////////////////////
 void Texture::
 write_datagram(BamWriter *manager, Datagram &me) {
+  // We also need to write out the pixel buffer's format, even though
+  // that's not stored as part of the texture structure.
+  bool has_pbuffer = (_pbuffer != (PixelBuffer *)NULL);
+
+  // These properties are read in again by make_Texture(), above.
   ImageBuffer::write_datagram(manager, me);
+  if (has_pbuffer) {
+    me.add_uint8(_pbuffer->get_num_components());
+  } else {
+    me.add_uint8(0);
+  }
+
+  // These properties are read in again by fillin(), above.
   me.add_uint8(_wrapu);
   me.add_uint8(_wrapv);
   me.add_uint8(_minfilter);
   me.add_uint8(_magfilter);
   me.add_int16(_anisotropic_degree);
 
-  // We also need to write out the pixel buffer's format, even though
-  // that's not stored as part of the texture structure.
-  bool has_pbuffer = (_pbuffer != (PixelBuffer *)NULL);
   me.add_bool(has_pbuffer);
   if (has_pbuffer) {
     me.add_uint8(_pbuffer->get_format());
+    // I know this has already been written, above.
     me.add_uint8(_pbuffer->get_num_components());
   }
 }

+ 3 - 2
panda/src/gobj/texture.h

@@ -79,8 +79,9 @@ PUBLISHED:
           bool bAllocateRAM);
   ~Texture();
 
-  bool read(const Filename &fullpath);
-  bool read(const Filename &fullpath, const Filename &alpha_fullpath);
+  bool read(const Filename &fullpath, int num_components = 0);
+  bool read(const Filename &fullpath, const Filename &alpha_fullpath,
+            int num_components = 0);
   bool write(const Filename &fullpath = "") const;
 
   void set_wrapu(WrapMode wrap);

+ 5 - 4
panda/src/gobj/texturePool.I

@@ -52,8 +52,8 @@ verify_texture(const string &filename) {
 //               file cannot be found, returns NULL.
 ////////////////////////////////////////////////////////////////////
 INLINE Texture *TexturePool::
-load_texture(const string &filename) {
-  return get_ptr()->ns_load_texture(filename);
+load_texture(const string &filename, int num_components) {
+  return get_ptr()->ns_load_texture(filename, num_components);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -66,8 +66,9 @@ load_texture(const string &filename) {
 //               file cannot be found, returns NULL.
 ////////////////////////////////////////////////////////////////////
 INLINE Texture *TexturePool::
-load_texture(const string &filename, const string &alpha_filename) {
-  return get_ptr()->ns_load_texture(filename, alpha_filename);
+load_texture(const string &filename, const string &alpha_filename,
+             int num_components) {
+  return get_ptr()->ns_load_texture(filename, alpha_filename, num_components);
 }
 
 ////////////////////////////////////////////////////////////////////

+ 6 - 5
panda/src/gobj/texturePool.cxx

@@ -65,7 +65,7 @@ ns_has_texture(const Filename &orig_filename) {
 //  Description: The nonstatic implementation of load_texture().
 ////////////////////////////////////////////////////////////////////
 Texture *TexturePool::
-ns_load_texture(const Filename &orig_filename) {
+ns_load_texture(const Filename &orig_filename, int num_components) {
   Filename filename(orig_filename);
 
   if (!fake_texture_image.empty()) {
@@ -92,7 +92,7 @@ ns_load_texture(const Filename &orig_filename) {
   gobj_cat.info()
     << "Loading texture " << filename << "\n";
   PT(Texture) tex = new Texture;
-  if (!tex->read(filename)) {
+  if (!tex->read(filename, num_components)) {
     // This texture was not found.
     gobj_cat.error()
       << "Unable to read texture " << filename << "\n";
@@ -113,12 +113,13 @@ ns_load_texture(const Filename &orig_filename) {
 ////////////////////////////////////////////////////////////////////
 Texture *TexturePool::
 ns_load_texture(const Filename &orig_filename, 
-                const Filename &orig_alpha_filename) {
+                const Filename &orig_alpha_filename,
+                int num_components) {
   Filename filename(orig_filename);
   Filename alpha_filename(orig_alpha_filename);
 
   if (!fake_texture_image.empty()) {
-    return ns_load_texture(fake_texture_image);
+    return ns_load_texture(fake_texture_image, num_components);
   }
 
   if (use_vfs) {
@@ -148,7 +149,7 @@ ns_load_texture(const Filename &orig_filename,
     << "Loading texture " << filename << " and alpha component "
     << alpha_filename << endl;
   PT(Texture) tex = new Texture;
-  if (!tex->read(filename, alpha_filename)) {
+  if (!tex->read(filename, alpha_filename, num_components)) {
     // This texture was not found.
     gobj_cat.error() << "Unable to read texture " << filename << "\n";
     return NULL;

+ 9 - 8
panda/src/gobj/texturePool.h

@@ -19,11 +19,9 @@
 #ifndef TEXTUREPOOL_H
 #define TEXTUREPOOL_H
 
-#include <pandabase.h>
-
+#include "pandabase.h"
 #include "texture.h"
-
-#include <filename.h>
+#include "filename.h"
 
 #include "pmap.h"
 
@@ -42,9 +40,11 @@ PUBLISHED:
   // language.
   INLINE static bool has_texture(const string &filename);
   INLINE static bool verify_texture(const string &filename);
-  INLINE static Texture *load_texture(const string &filename);
+  INLINE static Texture *load_texture(const string &filename, 
+                                      int num_components = 0);
   INLINE static Texture *load_texture(const string &filename,
-                                      const string &alpha_filename);
+                                      const string &alpha_filename, 
+                                      int num_components = 0);
   INLINE static void add_texture(Texture *texture);
   INLINE static void release_texture(Texture *texture);
   INLINE static void release_all_textures();
@@ -57,9 +57,10 @@ private:
   INLINE TexturePool();
 
   bool ns_has_texture(const Filename &orig_filename);
-  Texture *ns_load_texture(const Filename &orig_filename);
+  Texture *ns_load_texture(const Filename &orig_filename, int num_components);
   Texture *ns_load_texture(const Filename &orig_filename, 
-                           const Filename &orig_alpha_filename);
+                           const Filename &orig_alpha_filename, 
+                           int num_components);
   void ns_add_texture(Texture *texture);
   void ns_release_texture(Texture *texture);
   void ns_release_all_textures();

+ 2 - 1
panda/src/putil/bam.h

@@ -34,8 +34,9 @@ static const unsigned short _bam_major_ver = 4;
 // Bumped to major version 3 on 12/8/00 to change float64's to float32's.
 // Bumped to major version 4 on 4/10/02 to store new scene graph.
 
-static const unsigned short _bam_minor_ver = 1;
+static const unsigned short _bam_minor_ver = 2;
 // Bumped to minor version 1 on 4/10/03 to add CullFaceAttrib::reverse.
+// Bumped to minor version 2 on 4/12/03 to add num_components to texture.
 
 
 #endif