diff --git a/src/Main/fg_props.cxx b/src/Main/fg_props.cxx index f370ada19..42b07265a 100644 --- a/src/Main/fg_props.cxx +++ b/src/Main/fg_props.cxx @@ -356,6 +356,48 @@ setGoalViewOffset (double offset) ->set_goal_view_offset(offset * SGD_DEGREES_TO_RADIANS); } +/** + * Get the current view tilt in degrees. + */ +static double +getViewTilt () +{ + return (globals->get_current_view() + ->get_view_tilt() * SGD_RADIANS_TO_DEGREES); +} + + +static void +setViewTilt (double tilt) +{ + globals->get_current_view()->set_view_tilt(tilt * SGD_DEGREES_TO_RADIANS); +} + +static double +getGoalViewTilt () +{ + return (globals->get_current_view() + ->get_goal_view_tilt() * SGD_RADIANS_TO_DEGREES); +} + +static void +setGoalViewTilt (double tilt) +{ + while ( tilt < 0 ) { + tilt += 360.0; + } + while ( tilt > 360.0 ) { + tilt -= 360.0; + } + // Snap to center if we are close + if ( fabs(tilt) < 1.0 || fabs(tilt) > 359.0 ) { + tilt = 0.0; + } + + globals->get_current_view() + ->set_goal_view_tilt(tilt * SGD_DEGREES_TO_RADIANS); +} + /** * Pilot position offset from CG. @@ -1051,6 +1093,9 @@ fgInitProps () fgTie("/sim/view/offset-deg", getViewOffset, setViewOffset, false); fgSetArchivable("/sim/view/offset-deg"); fgTie("/sim/view/goal-offset-deg", getGoalViewOffset, setGoalViewOffset, false); + fgTie("/sim/view/tilt-deg", getViewTilt, setViewTilt, false); + fgSetArchivable("/sim/view/tilt-deg"); + fgTie("/sim/view/goal-tilt-deg", getGoalViewTilt, setGoalViewTilt, false); fgSetArchivable("/sim/view/goal-offset-deg"); fgTie("/sim/view/pilot/x-offset-m", getPilotPositionXOffset, setPilotPositionXOffset); diff --git a/src/Main/viewer.cxx b/src/Main/viewer.cxx index c13e17806..a06a1bbf6 100644 --- a/src/Main/viewer.cxx +++ b/src/Main/viewer.cxx @@ -38,7 +38,9 @@ FGViewer::FGViewer( void ): fov(55.0), view_offset(0.0), - goal_view_offset(0.0) + goal_view_offset(0.0), + view_tilt(0.0), + goal_view_tilt(0.0) { sgSetVec3( pilot_offset, 0.0, 0.0, 0.0 ); sgdZeroVec3(geod_view_pos); @@ -104,4 +106,33 @@ FGViewer::update (int dt) } } } + + for ( int i = 0; i < dt; i++ ) { + if ( fabs(get_goal_view_tilt() - get_view_tilt()) < 0.05 ) { + set_view_tilt( get_goal_view_tilt() ); + break; + } else { + // move current_view.view_tilt towards + // current_view.goal_view_tilt + if ( get_goal_view_tilt() > get_view_tilt() ) + { + if ( get_goal_view_tilt() - get_view_tilt() < SGD_PI ){ + inc_view_tilt( 0.01 ); + } else { + inc_view_tilt( -0.01 ); + } + } else { + if ( get_view_tilt() - get_goal_view_tilt() < SGD_PI ){ + inc_view_tilt( -0.01 ); + } else { + inc_view_tilt( 0.01 ); + } + } + if ( get_view_tilt() > SGD_2PI ) { + inc_view_tilt( -SGD_2PI ); + } else if ( get_view_tilt() < 0 ) { + inc_view_tilt( SGD_2PI ); + } + } + } } diff --git a/src/Main/viewer.hxx b/src/Main/viewer.hxx index e5307f3de..64cee08de 100644 --- a/src/Main/viewer.hxx +++ b/src/Main/viewer.hxx @@ -78,6 +78,10 @@ protected: // the goal view offset angle (used for smooth view changes) double goal_view_offset; + // the view tilt angles + double view_tilt; + double goal_view_tilt; + // geodetic view position sgdVec3 geod_view_pos; @@ -168,6 +172,24 @@ public: inline void set_reverse_view_offset( bool val ) { reverse_view_offset = val; } + inline void set_view_tilt( double a ) { + set_dirty(); + view_tilt = a; + } + inline void inc_view_tilt( double amt ) { + set_dirty(); + view_tilt += amt; + } + inline void set_goal_view_tilt( double a) { + set_dirty(); + goal_view_tilt = a; + while ( goal_view_tilt < 0 ) { + goal_view_tilt += 360.0; + } + while ( goal_view_tilt > 360.0 ) { + goal_view_tilt -= 360.0; + } + } inline void set_geod_view_pos( double lon, double lat, double alt ) { // data should be in radians and meters asl set_dirty(); @@ -197,6 +219,8 @@ public: inline double get_view_offset() const { return view_offset; } inline bool get_reverse_view_offset() const { return reverse_view_offset; } inline double get_goal_view_offset() const { return goal_view_offset; } + inline double get_view_tilt() const { return view_tilt; } + inline double get_goal_view_tilt() const { return goal_view_tilt; } inline double *get_geod_view_pos() { return geod_view_pos; } inline float *get_pilot_offset() { return pilot_offset; } inline double get_sea_level_radius() const { return sea_level_radius; }