fix keystone correction logic

This commit is contained in:
David Rose 2004-12-15 23:41:10 +00:00
parent c07989aace
commit ea4c5d4414
8 changed files with 250 additions and 160 deletions

View File

@ -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);
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."));
// 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.
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."));
// These are filled in by the ConfigureFn block, below.
bool textures_up_power_2 = false;
bool textures_down_power_2 = false;
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."));
// 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;
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."));
// 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);
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."));
// 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);
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."));
// 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);
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."));
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."));
// Set this to specify how textures should be written into Bam files.
// Currently, the options are:
ConfigVariableDouble default_keystone
("default-keystone", 0.0f,
PRC_DESC("The default keystone correction, as an x y pair, for all cameras."));
// 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;
}
gobj_cat->error() << "Invalid bam-texture-mode: " << mode << "\n";
return BTM_relative;
}
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);
}
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;
}

View File

@ -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);
extern const float default_near;
extern const float default_far;
extern const float default_fov;
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 ConfigVariableDouble default_near;
extern ConfigVariableDouble default_far;
extern ConfigVariableDouble default_fov;
extern ConfigVariableDouble default_keystone;
#endif

View File

@ -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

View File

@ -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;
}

View File

@ -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;

View File

@ -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 ||

View File

@ -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

View File

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