瀏覽代碼

fix keystone correction logic

David Rose 21 年之前
父節點
當前提交
ea4c5d4414

+ 165 - 116
panda/src/gobj/config_gobj.cxx

@@ -39,131 +39,90 @@
 Configure(config_gobj);
 NotifyCategoryDef(gobj, "");
 
-// Set this to the maximum size a texture is allowed to be in either
-// dimension.  This is generally intended as a simple way to restrict
-// texture sizes for limited graphics cards.  When this is greater
-// than zero, each texture image loaded from a file (but only those
-// loaded from a file) will be automatically scaled down, if
-// 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 true to retain the ram image for each texture after it
-// has been prepared with the GSG.  This will allow the texture to be
-// prepared with multiple GSG, or to be re-prepared later after it is
-// explicitly released from the GSG, without having to reread the
-// texture image from disk; but it will consume memory somewhat
-// wastefully.
-bool keep_texture_ram = config_gobj.GetBool("keep-texture-ram", false);
-
-// Ditto for Geom's.  This is a little more dangerous, because if
-// anyone calls release_all_geoms() on the GSG, we won't be able to
-// restore them automatically.
-bool keep_geom_ram = config_gobj.GetBool("keep-geom-ram", true);
-
-// Set this true to allow the use of retained mode rendering, which
-// creates specific cache information (like display lists or vertex
-// buffers) with the GSG for static geometry, when supported by the
-// GSG.  Set it false to use only immediate mode, which sends the
-// vertices to the GSG every frame.
-bool retained_mode = config_gobj.GetBool("retained-mode", false);
-
-
-// Set this to specify how textures should be written into Bam files.
-// Currently, the options are:
-
-//    fullpath - write the full pathname loaded.
-//    relative - search for the texture as a filename relative to the
-//               model-path or texture-path and write the relative pathname.
-//    basename - write only the basename of the file, no directory portion
-//               at all.
-
-BamTextureMode bam_texture_mode;
-
-// Set this to enable a speedy-load mode where you don't care what the
-// world looks like, you just want it to load in minimal time.  This
-// causes all texture loads via the TexturePool to load the same
-// texture file, which will presumably only be loaded once.
-const string fake_texture_image = config_gobj.GetString("fake-texture-image", "");
-
-// The default near and far plane distances.
-const float default_near = config_gobj.GetFloat("default-near", 1.0f);
-const float default_far = config_gobj.GetFloat("default-far", 1000.0f);
-
-// The default camera FOV.
-const float default_fov = config_gobj.GetFloat("default-fov", 40.0f);
-
-static BamTextureMode
-parse_texture_mode(const string &mode) {
-  if (cmp_nocase(mode, "unchanged") == 0) {
-    return BTM_unchanged;
-  } else if (cmp_nocase(mode, "fullpath") == 0) {
-    return BTM_fullpath;
-  } else if (cmp_nocase(mode, "relative") == 0) {
-    return BTM_relative;
-  } else if (cmp_nocase(mode, "basename") == 0) {
-    return BTM_basename;
-  } else if (cmp_nocase(mode, "rawdata") == 0) {
-    return BTM_rawdata;
-  }
+ConfigVariableInt max_texture_dimension
+("max-texture-dimension", -1,
+ PRC_DESC("Set this to the maximum size a texture is allowed to be in either "
+          "dimension.  This is generally intended as a simple way to restrict "
+          "texture sizes for limited graphics cards.  When this is greater "
+          "than zero, each texture image loaded from a file (but only those "
+          "loaded from a file) will be automatically scaled down, if "
+          "necessary, so that neither dimension is larger than this value."));
 
-  gobj_cat->error() << "Invalid bam-texture-mode: " << mode << "\n";
-  return BTM_relative;
-}
+ConfigVariableBool keep_texture_ram
+("keep-texture-ram", false,
+ PRC_DESC("Set this to true to retain the ram image for each texture after it "
+          "has been prepared with the GSG.  This will allow the texture to be "
+          "prepared with multiple GSG, or to be re-prepared later after it is "
+          "explicitly released from the GSG, without having to reread the "
+          "texture image from disk; but it will consume memory somewhat "
+          "wastefully."));
 
-ConfigureFn(config_gobj) {
-  string texture_mode = config_util.GetString("bam-texture-mode", "relative");
-  bam_texture_mode = parse_texture_mode(texture_mode);
+ConfigVariableBool keep_geom_ram
+("keep-geom-ram", true,
+ PRC_DESC("Set this to true to retain the vertices in ram for each geom "
+          "after it has been prepared with the GSG.  This is similar to "
+          "keep-texture-ram, but it is a little more dangerous, because if "
+          "anyone calls release_all_geoms() on the GSG (or if there are "
+          "multiple GSG's rendering a given geom), Panda won't be able to "
+          "restore the vertices."));
 
-  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;
+ConfigVariableBool retained_mode
+("retained-mode", false,
+ PRC_DESC("Set this true to allow the use of retained mode rendering, which "
+          "creates specific cache information (like display lists or vertex "
+          "buffers) with the GSG for static geometry, when supported by the "
+          "GSG.  Set it false to use only immediate mode, which sends the "
+          "vertices to the GSG every frame."));
 
-  } 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);
-  }
+ConfigVariableEnum<BamTextureMode> bam_texture_mode
+("bam-texture-mode", BTM_relative,
+ PRC_DESC("Set this to specify how textures should be written into Bam files."
+          "See the panda source or documentation for available options."));
 
-  string textures_square = config_gobj.GetString("textures-square", "");
-  if (cmp_nocase(textures_square, "up") == 0) {
-    textures_up_square = true;
-    textures_down_square = false;
+ConfigVariableEnum<AutoTextureScale> textures_power_2
+("textures-power-2", ATS_down,
+ PRC_DESC("Specify whether textures should automatically be constrained to "
+          "dimensions which are a power of 2 when they are loaded from "
+          "disk.  Set this to 'none' to disable this feature, or to "
+          "'down' or 'up' to scale down or up to the nearest power of 2, "
+          "respectively.  This only has effect on textures which are not "
+          "already a power of 2."));
 
-  } else if (cmp_nocase(textures_square, "down") == 0) {
-    textures_up_square = false;
-    textures_down_square = true;
+ConfigVariableEnum<AutoTextureScale> textures_square
+("textures-square", ATS_none,
+ PRC_DESC("Specify whether textures should automatically be constrained to "
+          "a square aspect ratio when they are loaded from disk.  Set this "
+          "to 'none', 'down', or 'up'.  See textures-power-2."));
 
-  } else {
-    textures_up_square = false;
-    textures_down_square = config_gobj.GetBool("textures-square", false);
-  }
+ConfigVariableString fake_texture_image
+("fake-texture-image", "",
+ PRC_DESC("Set this to enable a speedy-load mode in which you don't care "
+          "what the world looks like, you just want it to load in minimal "
+          "time.  This causes all texture loads via the TexturePool to use "
+          "the same texture file, which will presumably only be loaded "
+          "once."));
+
+ConfigVariableDouble default_near
+("default-near", 1.0,
+ PRC_DESC("The default near clipping distance for all cameras."));
+
+ConfigVariableDouble default_far
+("default-far", 1000.0,
+ PRC_DESC("The default far clipping distance for all cameras."));
+
+ConfigVariableDouble default_fov
+("default-fov", 40.0,
+ PRC_DESC("The default field of view in degrees for all cameras."));
 
+
+ConfigVariableDouble default_keystone
+("default-keystone", 0.0f,
+ PRC_DESC("The default keystone correction, as an x y pair, for all cameras."));
+
+
+
+ConfigureFn(config_gobj) {
   BoundedObject::init_type();
   Geom::init_type();
   GeomLine::init_type();
@@ -208,3 +167,93 @@ ConfigureFn(config_gobj) {
   TextureStage::register_with_read_factory();
   TexCoordName::register_with_read_factory();
 }
+
+ostream &
+operator << (ostream &out, BamTextureMode btm) {
+  switch (btm) {
+  case BTM_unchanged:
+    return out << "unchanged";
+   
+  case BTM_fullpath:
+    return out << "fullpath";
+    
+  case BTM_relative:
+    return out << "relative";
+    
+  case BTM_basename:
+    return out << "basename";
+
+  case BTM_rawdata:
+    return out << "rawdata";
+  }
+
+  return out << "**invalid BamTextureMode (" << (int)btm << ")**";
+}
+
+istream &
+operator >> (istream &in, BamTextureMode &btm) {
+  string word;
+  in >> word;
+
+  if (cmp_nocase(word, "unchanged") == 0) {
+    btm = BTM_unchanged;
+  } else if (cmp_nocase(word, "fullpath") == 0) {
+    btm = BTM_fullpath;
+  } else if (cmp_nocase(word, "relative") == 0) {
+    btm = BTM_relative;
+  } else if (cmp_nocase(word, "basename") == 0) {
+    btm = BTM_basename;
+  } else if (cmp_nocase(word, "rawdata") == 0) {
+    btm = BTM_rawdata;
+
+  } else {
+    gobj_cat->error() << "Invalid BamTextureMode value: " << word << "\n";
+    btm = BTM_relative;
+  }
+
+  return in;
+}
+
+ostream &
+operator << (ostream &out, AutoTextureScale ats) {
+  switch (ats) {
+  case ATS_none:
+    return out << "none";
+   
+  case ATS_down:
+    return out << "down";
+    
+  case ATS_up:
+    return out << "up";
+  }
+
+  return out << "**invalid AutoTextureScale (" << (int)ats << ")**";
+}
+
+istream &
+operator >> (istream &in, AutoTextureScale &ats) {
+  string word;
+  in >> word;
+
+  if (cmp_nocase(word, "none") == 0 ||
+      cmp_nocase(word, "0") == 0 ||
+      cmp_nocase(word, "#f") == 0 ||
+      tolower(word[0] == 'f')) {
+    ats = ATS_none;
+
+  } else if (cmp_nocase(word, "down") == 0 ||
+          cmp_nocase(word, "1") == 0 ||
+          cmp_nocase(word, "#t") == 0 ||
+          tolower(word[0] == 't')) {
+    ats = ATS_down;
+
+  } else if (cmp_nocase(word, "up") == 0) {
+    ats = ATS_up;
+
+  } else {
+    gobj_cat->error() << "Invalid AutoTextureScale value: " << word << "\n";
+    ats = ATS_none;
+  }
+
+  return in;
+}

+ 29 - 15
panda/src/gobj/config_gobj.h

@@ -21,19 +21,13 @@
 
 #include "pandabase.h"
 #include "notifyCategoryProxy.h"
+#include "configVariableBool.h"
+#include "configVariableInt.h"
+#include "configVariableEnum.h"
+#include "configVariableDouble.h"
 
 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;
-extern EXPCL_PANDA bool keep_texture_ram;
-extern EXPCL_PANDA bool keep_geom_ram;
-extern EXPCL_PANDA bool retained_mode;
-
 enum BamTextureMode {
   BTM_unchanged,
   BTM_fullpath,
@@ -41,12 +35,32 @@ enum BamTextureMode {
   BTM_basename,
   BTM_rawdata
 };
-extern EXPCL_PANDA BamTextureMode bam_texture_mode;
-extern EXPCL_PANDA const string fake_texture_image;
+ostream &operator << (ostream &out, BamTextureMode btm);
+istream &operator >> (istream &in, BamTextureMode &btm);
+
+enum AutoTextureScale {
+  ATS_none,
+  ATS_down,
+  ATS_up
+};
+ostream &operator << (ostream &out, AutoTextureScale ats);
+istream &operator >> (istream &in, AutoTextureScale &ats);
+
+// Configure variables for gobj package.
+extern EXPCL_PANDA ConfigVariableInt max_texture_dimension;
+extern EXPCL_PANDA ConfigVariableBool keep_texture_ram;
+extern EXPCL_PANDA ConfigVariableBool keep_geom_ram;
+extern EXPCL_PANDA ConfigVariableBool retained_mode;
+
+extern EXPCL_PANDA ConfigVariableEnum<BamTextureMode> bam_texture_mode;
+extern EXPCL_PANDA ConfigVariableEnum<AutoTextureScale> textures_power_2;
+extern EXPCL_PANDA ConfigVariableEnum<AutoTextureScale> textures_square;
+extern EXPCL_PANDA ConfigVariableString fake_texture_image;
 
-extern const float default_near;
-extern const float default_far;
-extern const float default_fov;
+extern ConfigVariableDouble default_near;
+extern ConfigVariableDouble default_far;
+extern ConfigVariableDouble default_fov;
+extern ConfigVariableDouble default_keystone;
 
 #endif
 

+ 11 - 0
panda/src/gobj/lens.I

@@ -391,6 +391,17 @@ set_view_vector(float x, float y, float z, float i, float j, float k) {
   set_view_vector(LVector3f(x, y, z), LVector3f(i, j, k));
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: Lens::get_keystone
+//       Access: Published
+//  Description: Returns the keystone correction specified for the
+//               lens.
+////////////////////////////////////////////////////////////////////
+INLINE const LVecBase2f &Lens::
+get_keystone() const {
+  return _keystone;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: Lens::get_last_change
 //       Access: Public

+ 20 - 22
panda/src/gobj/lens.cxx

@@ -105,10 +105,16 @@ clear() {
   _view_vector.set(0.0f, 1.0f, 0.0f);
   _up_vector.set(0.0f, 0.0f, 1.0f);
   _iod_offset = 0.0f;
-  _keystone.set(0.0f, 0.0f, 0.0f);
+  _keystone.set(0.0f, 0.0f);
+
   _user_flags = 0;
   _comp_flags = CF_fov;
 
+  if (default_keystone.has_value()) {
+    _keystone.set(default_keystone[0], default_keystone[1]);
+    _user_flags |= UF_keystone;
+  }
+
   // Assign an initial arbitrary sequence to these three.
   _film_size_seq = 0;
   _focal_length_seq = 1;
@@ -598,38 +604,30 @@ clear_view_mat() {
 //               matrix that will compensate for keystoning of a
 //               projected image; this can be used to compensate for a
 //               projector that for physical reasons cannot be aimed
-//               directly at it screen.  The default value of 0, 0, 0
-//               indicates no keystone correction; specify a small
-//               value (usually in the range -1 .. 1) in one of the
-//               three axes to generate a keystone correction in that
-//               axis.
+//               directly at it screen.  
+//
+//               The default value is taken from the default-keystone
+//               Config variable.  0, 0 indicates no keystone
+//               correction; specify a small value (usually in the
+//               range -1 .. 1) in either the x or y position to
+//               generate a keystone correction in that axis.
 ////////////////////////////////////////////////////////////////////
 void Lens::
-set_keystone(const LVecBase3f &keystone) {
+set_keystone(const LVecBase2f &keystone) {
   _keystone = keystone;
   adjust_user_flags(0, UF_keystone);
   adjust_comp_flags(CF_projection_mat | CF_projection_mat_inv | CF_film_mat | CF_film_mat_inv, 0);
   throw_change_event();
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: Lens::get_keystone
-//       Access: Published
-//  Description: Returns the direction in which the lens is facing.
-////////////////////////////////////////////////////////////////////
-const LVecBase3f &Lens::
-get_keystone() const {
-  return _keystone;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: Lens::clear_keystone
 //       Access: Published
-//  Description: Resets the lens transform to identity.
+//  Description: Disables the lens keystone correction.
 ////////////////////////////////////////////////////////////////////
 void Lens::
 clear_keystone() {
-  _keystone = LVecBase3f(0.0f, 0.0f, 0.0f);
+  _keystone.set(0.0f, 0.0f);
   adjust_user_flags(UF_keystone, 0);
   adjust_comp_flags(CF_projection_mat | CF_projection_mat_inv | CF_film_mat | CF_film_mat_inv, 0);
   throw_change_event();
@@ -1449,9 +1447,9 @@ compute_film_mat() {
         -film_offset[0] * scale_x, -film_offset[1] * scale_y, 0.0f,  1.0f);
 
   if ((_user_flags & UF_keystone) != 0) {
-    _film_mat = LMatrix4f(csqrt(1.0f - _keystone[0] * _keystone[0]), 0.0f, 0.0f, _keystone[0],
-                          0.0f, csqrt(1.0f - _keystone[1] * _keystone[1]), 0.0f, _keystone[1],
-                          0.0f, 0.0f, csqrt(1.0f - _keystone[2] * _keystone[2]), _keystone[2],
+    _film_mat = LMatrix4f(1.0f, 0.0f, _keystone[0], _keystone[0],
+                          0.0f, 1.0f, _keystone[1], _keystone[1],
+                          0.0f, 0.0f, 1.0f, 0.0f,
                           0.0f, 0.0f, 0.0f, 1.0f) * _film_mat;
   }
 

+ 4 - 3
panda/src/gobj/lens.h

@@ -112,8 +112,8 @@ PUBLISHED:
   const LMatrix4f &get_view_mat() const;
   void clear_view_mat();
 
-  void set_keystone(const LVecBase3f &keystone);
-  const LVecBase3f &get_keystone() const;
+  void set_keystone(const LVecBase2f &keystone);
+  INLINE const LVecBase2f &get_keystone() const;
   void clear_keystone();
   
   // These flags are passed in as the last parameter to control the
@@ -125,6 +125,7 @@ PUBLISHED:
     FC_off_axis     = 0x0004,
     FC_aspect_ratio = 0x0008,
     FC_shear        = 0x0010,
+    FC_keystone     = 0x0020,
   };
   void set_frustum_from_corners(const LVecBase3f &ul, const LVecBase3f &ur,
                                 const LVecBase3f &ll, const LVecBase3f &lr,
@@ -202,7 +203,7 @@ protected:
   LVecBase3f _view_hpr;
   LVector3f _view_vector, _up_vector;
   float _iod_offset;
-  LVecBase3f _keystone;
+  LVecBase2f _keystone;
 
   LMatrix4f _film_mat, _film_mat_inv;
   LMatrix4f _lens_mat, _lens_mat_inv;

+ 20 - 6
panda/src/gobj/texture.cxx

@@ -71,23 +71,37 @@ 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) {
+  switch (textures_power_2) {
+  case ATS_down:
     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) {
+    break;
+
+  case ATS_up:
     new_x_size = up_to_power_2(new_x_size);
     new_y_size = up_to_power_2(new_y_size);
+    break;
+
+  case ATS_none:
+    break;
   }
 
-  if (textures_down_square) {
+  switch (textures_square) {
+  case ATS_down:
     new_x_size = new_y_size = min(new_x_size, new_y_size);
-  } else if (textures_up_square) {
+    break;
+
+  case ATS_up:
     new_x_size = new_y_size = max(new_x_size, new_y_size);
+    break;
+
+  case ATS_none:
+    break;
   }
 
   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);
+    new_x_size = min(new_x_size, (int)max_texture_dimension);
+    new_y_size = min(new_y_size, (int)max_texture_dimension);
   }
 
   if (pnmimage.get_x_size() != new_x_size ||

+ 2 - 2
panda/src/grutil/multitexReducer.cxx

@@ -620,8 +620,8 @@ choose_texture_size(int &x_size, int &y_size,
 
   // Constrain the x_size and y_size to the max_texture_dimension.
   if (max_texture_dimension > 0) {
-    x_size = min(x_size, max_texture_dimension);
-    y_size = min(y_size, max_texture_dimension);
+    x_size = min(x_size, (int)max_texture_dimension);
+    y_size = min(y_size, (int)max_texture_dimension);
   }
 
   // Finally, make sure the new sizes fit within the window, so we can

+ 3 - 0
panda/src/pgraph/transparencyAttrib.cxx

@@ -83,6 +83,9 @@ output(ostream &out) const {
   case M_dual:
     out << "dual";
     break;
+
+  case M_notused:
+    break;
   }
 }