diff --git a/src/Main/options.cxx b/src/Main/options.cxx index 9e9979c95..b27f37843 100644 --- a/src/Main/options.cxx +++ b/src/Main/options.cxx @@ -1263,6 +1263,7 @@ struct OptionDesc { {"enable-clouds3d", false, OPTION_BOOL, "/sim/rendering/clouds3d", true, "", 0 }, #endif {"fov", true, OPTION_FUNC, "", false, "", fgOptFov }, + {"aspect-ratio-multiplier", true, OPTION_DOUBLE, "/sim/current-view/aspect-ratio-multiplier", false, "", 0 }, {"disable-fullscreen", false, OPTION_BOOL, "/sim/startup/fullscreen", false, "", 0 }, {"enable-fullscreen", false, OPTION_BOOL, "/sim/startup/fullscreen", true, "", 0 }, {"shading-flat", false, OPTION_BOOL, "/sim/rendering/shading", false, "", 0 }, diff --git a/src/Main/renderer.cxx b/src/Main/renderer.cxx index 93ef926ca..7879eee20 100644 --- a/src/Main/renderer.cxx +++ b/src/Main/renderer.cxx @@ -797,6 +797,9 @@ FGRenderer::resize( int width, int height ) { setFOV( viewmgr->get_current_view()->get_h_fov(), viewmgr->get_current_view()->get_v_fov() ); + // cout << "setFOV(" << viewmgr->get_current_view()->get_h_fov() + // << ", " << viewmgr->get_current_view()->get_v_fov() << ")" + // << endl; #ifdef FG_USE_CLOUDS_3D sgClouds3d->Resize( viewmgr->get_current_view()->get_h_fov(), @@ -843,7 +846,10 @@ static void fgHackFrustum() { // interface to the display callback system. There's probably a // better way, there has to be a better way, but I'm not seeing it // right now. -static float width, height, near, far; +static float width = 55.0; +static float height = 42.0; +static float near = 1.0; +static float far = 1000.0; /** FlightGear code should use this routine to set the FOV rather than diff --git a/src/Main/viewer.cxx b/src/Main/viewer.cxx index b39b14144..74f25e834 100644 --- a/src/Main/viewer.cxx +++ b/src/Main/viewer.cxx @@ -176,7 +176,8 @@ FGViewer::FGViewer( fgViewType Type, bool from_model, int from_model_index, double damp_roll, double damp_pitch, double damp_heading, double x_offset_m, double y_offset_m, double z_offset_m, double heading_offset_deg, double pitch_offset_deg, - double roll_offset_deg, double fov_deg, + double roll_offset_deg, + double fov_deg, double aspect_ratio_multiplier, double target_x_offset_m, double target_y_offset_m, double target_z_offset_m, double near_m, bool internal ): _dirty(true), @@ -225,6 +226,7 @@ FGViewer::FGViewer( fgViewType Type, bool from_model, int from_model_index, } else { _fov_deg = 55; } + _aspect_ratio_multiplier = aspect_ratio_multiplier; _target_x_offset_m = target_x_offset_m; _target_y_offset_m = target_y_offset_m; _target_z_offset_m = target_z_offset_m; @@ -840,8 +842,10 @@ FGViewer::get_h_fov() return _fov_deg; } else { // v_fov == fov - return atan(tan(_fov_deg/2 * SG_DEGREES_TO_RADIANS) / _aspect_ratio) * - SG_RADIANS_TO_DEGREES * 2; + return + atan(tan(_fov_deg/2 * SG_DEGREES_TO_RADIANS) + / (_aspect_ratio*_aspect_ratio_multiplier)) + * SG_RADIANS_TO_DEGREES * 2; } default: assert(false); @@ -856,13 +860,17 @@ FGViewer::get_v_fov() { switch (_scaling_type) { case FG_SCALING_WIDTH: // h_fov == fov - return atan(tan(_fov_deg/2 * SG_DEGREES_TO_RADIANS) * _aspect_ratio) * - SG_RADIANS_TO_DEGREES * 2; + return + atan(tan(_fov_deg/2 * SG_DEGREES_TO_RADIANS) + * (_aspect_ratio*_aspect_ratio_multiplier)) + * SG_RADIANS_TO_DEGREES * 2; case FG_SCALING_MAX: if (_aspect_ratio < 1.0) { // h_fov == fov - return atan(tan(_fov_deg/2 * SG_DEGREES_TO_RADIANS) * _aspect_ratio) * - SG_RADIANS_TO_DEGREES * 2; + return + atan(tan(_fov_deg/2 * SG_DEGREES_TO_RADIANS) + * (_aspect_ratio*_aspect_ratio_multiplier)) + * SG_RADIANS_TO_DEGREES * 2; } else { // v_fov == fov return _fov_deg; diff --git a/src/Main/viewer.hxx b/src/Main/viewer.hxx index 67a13ee63..5907997e9 100644 --- a/src/Main/viewer.hxx +++ b/src/Main/viewer.hxx @@ -65,7 +65,8 @@ public: double damp_roll, double damp_pitch, double damp_heading, double x_offset_m, double y_offset_m, double z_offset_m, double heading_offset_deg, double pitch_offset_deg, - double roll_offset_deg, double fov_deg, + double roll_offset_deg, + double fov_deg, double aspect_ratio_multiplier, double target_x_offset_m, double target_y_offset_m, double target_z_offset_m, double near_m, bool internal ); @@ -245,6 +246,13 @@ public: } virtual double get_aspect_ratio() const { return _aspect_ratio; } + virtual void set_aspect_ratio_multiplier( double m ) { + _aspect_ratio_multiplier = m; + } + virtual double get_aspect_ratio_multiplier() const { + return _aspect_ratio_multiplier; + } + virtual double getNear_m () const { return _ground_level_nearplane_m; } inline void setNear_m (double near_m) { _ground_level_nearplane_m = near_m; @@ -343,8 +351,14 @@ private: // the nominal field of view (angle, in degrees) double _fov_deg; - // ratio of window width and height; height = width * aspect_ratio - double _aspect_ratio; + // Ratio of window width and height; height = width * + // aspect_ratio. This value is automatically calculated based on + // window dimentions. + double _aspect_ratio; + + // default = 1.0, this value is user configurable and is + // multiplied into the aspect_ratio to get the actual vertical fov + double _aspect_ratio_multiplier; bool _reverse_view_offset; diff --git a/src/Main/viewmgr.cxx b/src/Main/viewmgr.cxx index 371c38f7d..ad376d30a 100644 --- a/src/Main/viewmgr.cxx +++ b/src/Main/viewmgr.cxx @@ -54,6 +54,7 @@ FGViewMgr::init () // double damp_alt; double damp_roll = 0.0, damp_pitch = 0.0, damp_heading = 0.0; double x_offset_m, y_offset_m, z_offset_m, fov_deg; + double aspect_ratio_multiplier = 1.0; double heading_offset_deg, pitch_offset_deg, roll_offset_deg; double target_x_offset_m, target_y_offset_m, target_z_offset_m; double near_m; @@ -161,7 +162,7 @@ FGViewMgr::init () damp_roll, damp_pitch, damp_heading, x_offset_m, y_offset_m,z_offset_m, heading_offset_deg, pitch_offset_deg, - roll_offset_deg, fov_deg, + roll_offset_deg, fov_deg, aspect_ratio_multiplier, target_x_offset_m, target_y_offset_m, target_z_offset_m, near_m, internal )); else @@ -169,8 +170,8 @@ FGViewMgr::init () false, 0, 0.0, 0.0, 0.0, x_offset_m, y_offset_m, z_offset_m, heading_offset_deg, pitch_offset_deg, - roll_offset_deg, fov_deg, 0, 0, 0, near_m, - internal )); + roll_offset_deg, fov_deg, aspect_ratio_multiplier, + 0, 0, 0, near_m, internal )); } copyToCurrent(); @@ -297,6 +298,10 @@ FGViewMgr::bind () &FGViewMgr::getFOV_deg, &FGViewMgr::setFOV_deg); fgSetArchivable("/sim/current-view/field-of-view"); + fgTie("/sim/current-view/aspect-ratio-multiplier", this, + &FGViewMgr::getARM_deg, &FGViewMgr::setARM_deg); + fgSetArchivable("/sim/current-view/field-of-view"); + fgTie("/sim/current-view/ground-level-nearplane-m", this, &FGViewMgr::getNear_m, &FGViewMgr::setNear_m); fgSetArchivable("/sim/current-view/ground-level-nearplane-m"); @@ -312,7 +317,8 @@ FGViewMgr::unbind () fgUntie("/sim/current-view/goal-heading-offset-deg"); fgUntie("/sim/current-view/pitch-offset-deg"); fgUntie("/sim/current-view/goal-pitch-offset-deg"); - fgUntie("/sim/field-of-view"); + fgUntie("/sim/current-view/field-of-view"); + fgUntie("/sim/current-view/aspect-ratio-multiplier"); fgUntie("/sim/current-view/view-number"); fgUntie("/sim/current-view/axes/long"); fgUntie("/sim/current-view/axes/lat"); @@ -734,6 +740,21 @@ FGViewMgr::setFOV_deg (double fov) view->set_fov(fov); } +double +FGViewMgr::getARM_deg () const +{ + const FGViewer * view = get_current_view(); + return (view == 0 ? 0 : view->get_aspect_ratio_multiplier()); +} + +void +FGViewMgr::setARM_deg (double aspect_ratio_multiplier) +{ + FGViewer * view = get_current_view(); + if (view != 0) + view->set_aspect_ratio_multiplier(aspect_ratio_multiplier); +} + double FGViewMgr::getNear_m () const { diff --git a/src/Main/viewmgr.hxx b/src/Main/viewmgr.hxx index 23a9ac614..eff9d67ff 100644 --- a/src/Main/viewmgr.hxx +++ b/src/Main/viewmgr.hxx @@ -149,6 +149,8 @@ private: void setViewTargetZOffset_m (double z); double getFOV_deg () const; void setFOV_deg (double fov); + double getARM_deg () const; // Aspect Ratio Multiplier + void setARM_deg (double fov); double getNear_m () const; void setNear_m (double near_m); void setViewAxisLong (double axis);