Fix broken convergence distance calculation, adding a configuration variable to restore the old behavior if needed.

This commit is contained in:
rdb 2014-08-20 20:24:13 +00:00
parent 70f73a5ea1
commit bb7a6a3ec4
4 changed files with 50 additions and 20 deletions

View File

@ -510,6 +510,16 @@ ConfigVariableInt lens_geom_segments
"lens; for a normal perspective or orthographic lens, the "
"wireframe is not subdivided."));
ConfigVariableBool stereo_lens_old_convergence
("stereo-lens-old-convergence", false,
PRC_DESC("In Panda3D 1.8 and below, when using a stereo lens, Panda "
"generate an incorrect frustum skew for a given convergence "
"distance, meaning that the left-right images wouldn't "
"overlap at the configured distance. This calculation has "
"since been corrected, but if your application relies on the "
"old, incorrect behavior, this may be set to 'true' to switch "
"back to the old calculation."));
ConfigVariableString cg_glsl_version
("cg-glsl-version", "",
PRC_DESC("If this is set, it forces the Cg compiler to generate GLSL "
@ -604,10 +614,10 @@ operator << (ostream &out, ShaderUtilization sgc) {
switch (sgc) {
case SUT_none:
return out << "none";
case SUT_basic:
return out << "basic";
case SUT_advanced:
return out << "advanced";

View File

@ -98,6 +98,7 @@ extern EXPCL_PANDA_GOBJ ConfigVariableDouble adaptive_lru_weight;
extern EXPCL_PANDA_GOBJ ConfigVariableInt adaptive_lru_max_updates_per_frame;
extern EXPCL_PANDA_GOBJ ConfigVariableDouble async_load_delay;
extern EXPCL_PANDA_GOBJ ConfigVariableInt lens_geom_segments;
extern EXPCL_PANDA_GOBJ ConfigVariableBool stereo_lens_old_convergence;
extern EXPCL_PANDA_GOBJ ConfigVariableString cg_glsl_version;

View File

@ -608,14 +608,26 @@ get_interocular_distance() const {
// PerspectiveLens.
//
// This parameter must be greater than 0, but may be as
// large as you like. It controls the amount to which
// the two eyes are directed inwards towards each other,
// which is a normal property of stereo vision. It is a
// distance, not an angle; normally this should be set
// to the distance from the camera to the area of
// interest in your scene. If you want to simulate
// parallel stereo, set this value to a very large
// number.
// large as you like. It controls the distance at
// which the two stereo images will appear to converge,
// which is a normal property of stereo vision. Normally
// this should be set to the distance from the camera to
// the area of interest in your scene. Anything beyond
// this distance will appear to go into the screen, and
// anything closer will appear to come out of the screen.
// If you want to simulate parallel stereo, set this
// to infinity.
//
// Note that this creates an off-axis frustum, which
// means that the lenses are still pointing in the
// same direction, which is usually more desirable
// than the more naive toe-in approach, where the
// two lenses are simply tilted toward each other.
//
// Prior to Panda3D 1.9.0, the convergence was being
// calculated incorrectly. It has since been corrected.
// To restore the legacy behavior you can set the
// stereo-lens-old-convergence variable to true.
//
// Also see set_interocular_distance(), which relates.
////////////////////////////////////////////////////////////////////
@ -807,7 +819,7 @@ do_adjust_comp_flags(CData *cdata, int clear_flags, int set_flags) {
////////////////////////////////////////////////////////////////////
// Function: Lens::do_set_film_offset
// Access: Protected
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE void Lens::
do_set_film_offset(CData *cdata, const LVecBase2 &film_offset) {
@ -819,7 +831,7 @@ do_set_film_offset(CData *cdata, const LVecBase2 &film_offset) {
////////////////////////////////////////////////////////////////////
// Function: Lens::do_get_film_offset
// Access: Protected
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE const LVector2 &Lens::
do_get_film_offset(const CData *cdata) const {
@ -829,7 +841,7 @@ do_get_film_offset(const CData *cdata) const {
////////////////////////////////////////////////////////////////////
// Function: Lens::do_set_near
// Access: Protected
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE void Lens::
do_set_near(CData *cdata, PN_stdfloat near_distance) {
@ -841,7 +853,7 @@ do_set_near(CData *cdata, PN_stdfloat near_distance) {
////////////////////////////////////////////////////////////////////
// Function: Lens::do_get_near
// Access: Protected
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE PN_stdfloat Lens::
do_get_near(const CData *cdata) const {
@ -851,7 +863,7 @@ do_get_near(const CData *cdata) const {
////////////////////////////////////////////////////////////////////
// Function: Lens::do_set_far
// Access: Protected
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE void Lens::
do_set_far(CData *cdata, PN_stdfloat far_distance) {
@ -863,7 +875,7 @@ do_set_far(CData *cdata, PN_stdfloat far_distance) {
////////////////////////////////////////////////////////////////////
// Function: Lens::do_get_far
// Access: Protected
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE PN_stdfloat Lens::
do_get_far(const CData *cdata) const {
@ -873,7 +885,7 @@ do_get_far(const CData *cdata) const {
////////////////////////////////////////////////////////////////////
// Function: Lens::do_set_near_far
// Access: Protected
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE void Lens::
do_set_near_far(CData *cdata, PN_stdfloat near_distance, PN_stdfloat far_distance) {

View File

@ -137,10 +137,17 @@ do_compute_projection_mat(Lens::CData *lens_cdata) {
LVector3 iod = lens_cdata->_interocular_distance * 0.5f * LVector3::left(lens_cdata->_cs);
lens_cdata->_projection_mat_left = do_get_lens_mat_inv(lens_cdata) * LMatrix4::translate_mat(-iod) * canonical * do_get_film_mat(lens_cdata);
lens_cdata->_projection_mat_right = do_get_lens_mat_inv(lens_cdata) * LMatrix4::translate_mat(iod) * canonical * do_get_film_mat(lens_cdata);
if (lens_cdata->_user_flags & UF_convergence_distance) {
if ((lens_cdata->_user_flags & UF_convergence_distance) != 0 &&
!cinf(lens_cdata->_convergence_distance)) {
nassertv(lens_cdata->_convergence_distance != 0.0f);
LVector3 cd = (0.25f / lens_cdata->_convergence_distance) * LVector3::left(lens_cdata->_cs);
LVector3 cd;
if (stereo_lens_old_convergence) { // The old, incorrect calculation was requested.
cd = (0.25f / lens_cdata->_convergence_distance) * LVector3::left(lens_cdata->_cs);
} else {
const LVecBase2 &fov = do_get_fov(lens_cdata);
cd = (2.0f / fov_to_film(fov[0], lens_cdata->_convergence_distance, true)) * iod;
}
lens_cdata->_projection_mat_left *= LMatrix4::translate_mat(cd);
lens_cdata->_projection_mat_right *= LMatrix4::translate_mat(-cd);
}