diff --git a/src/Cockpit/cockpit.cxx b/src/Cockpit/cockpit.cxx index 5750035af..afbdb3140 100644 --- a/src/Cockpit/cockpit.cxx +++ b/src/Cockpit/cockpit.cxx @@ -259,7 +259,7 @@ float get_climb_rate( void ) float get_view_direction( void ) { - double view_off = SGD_2PI - globals->get_current_view()->get_view_offset(); + double view_off = SGD_2PI - globals->get_current_view()->getHeadingOffset_deg() * SGD_DEGREES_TO_RADIANS; double view = ( current_aircraft.fdm_state->get_Psi() + view_off) * SGD_RADIANS_TO_DEGREES; @@ -745,3 +745,4 @@ void fgCockpitUpdate( void ) { glViewport( 0, 0, iwidth, iheight ); } + diff --git a/src/Cockpit/panel.cxx b/src/Cockpit/panel.cxx index ab0ce2142..5443c0437 100644 --- a/src/Cockpit/panel.cxx +++ b/src/Cockpit/panel.cxx @@ -89,7 +89,7 @@ fgPanelVisible () return false; if(globals->get_viewmgr()->get_current() != 0) return false; - if(globals->get_current_view()->get_view_offset() != 0 && + if(globals->get_current_view()->getHeadingOffset_deg() * SGD_DEGREES_TO_RADIANS != 0 && !fgGetBool("/sim/virtual-cockpit")) return false; return true; @@ -452,8 +452,8 @@ FGPanel::setupVirtualCockpit() // Generate a "look at" matrix using OpenGL (!) coordinate // conventions. float lookat[3]; - float pitch = view->get_view_tilt(); - float rot = view->get_view_offset(); + float pitch = view->getPitchOffset_deg() * SGD_DEGREES_TO_RADIANS; + float rot = view->getHeadingOffset_deg() * SGD_DEGREES_TO_RADIANS; lookat[0] = -sin(rot); lookat[1] = sin(pitch) / cos(pitch); lookat[2] = -cos(rot); @@ -1150,3 +1150,4 @@ FGSwitchLayer::draw () // end of panel.cxx + diff --git a/src/GUI/mouse.cxx b/src/GUI/mouse.cxx index fa6609c1e..9e6fc7b26 100644 --- a/src/GUI/mouse.cxx +++ b/src/GUI/mouse.cxx @@ -175,20 +175,30 @@ static inline int right_button( void ) { static inline void set_goal_view_offset( float offset ) { - globals->get_current_view()->set_goal_view_offset(offset); + globals->get_current_view()->set_goal_view_offset(offset * SGD_RADIANS_TO_DEGREES); } static inline void set_view_offset( float offset ) { - globals->get_current_view()->set_view_offset(offset); + globals->get_current_view()->setHeadingOffset_deg(offset * SGD_RADIANS_TO_DEGREES); +} + +static inline void set_goal_view_tilt( float tilt ) +{ + globals->get_current_view()->set_goal_view_tilt(tilt); +} + +static inline void set_view_tilt( float tilt ) +{ + globals->get_current_view()->setPitchOffset_deg(tilt); } static inline float get_view_offset() { - return globals->get_current_view()->get_view_offset(); + return globals->get_current_view()->getHeadingOffset_deg() * SGD_DEGREES_TO_RADIANS; } static inline float get_goal_view_offset() { - return globals->get_current_view()->get_goal_view_offset(); + return globals->get_current_view()->get_goal_view_offset() * SGD_DEGREES_TO_RADIANS; } static inline void move_brake(float offset) { @@ -476,8 +486,10 @@ void guiMotionFunc ( int x, int y ) offset -= SGD_2PI; } set_goal_view_offset(offset); + set_goal_view_tilt(asin( GuiQuat_mat[1][2]) * SGD_RADIANS_TO_DEGREES ); #ifdef NO_SMOOTH_MOUSE_VIEW set_view_offset(offset); + set_view_tilt(asin( GuiQuat_mat[1][2]) * SGD_RADIANS_TO_DEGREES ); #endif break; @@ -532,6 +544,7 @@ void guiMouseFunc(int button, int updown, int x, int y) y = _Vy; sgCopyVec4(curGuiQuat, _quat); set_goal_view_offset(_view_offset); + set_goal_view_tilt(0.0); #ifdef NO_SMOOTH_MOUSE_VIEW set_view_offset(_view_offset); #endif @@ -547,8 +560,10 @@ void guiMouseFunc(int button, int updown, int x, int y) Quat0(); _view_offset = get_goal_view_offset(); set_goal_view_offset(0.0); + set_goal_view_tilt(0.0); #ifdef NO_SMOOTH_MOUSE_VIEW set_view_offset(0.0); + set_view_tilt(0.0); #endif } glutWarpPointer( x , y); @@ -605,8 +620,10 @@ void guiMouseFunc(int button, int updown, int x, int y) Quat0(); build_rotmatrix(GuiQuat_mat, curGuiQuat); set_goal_view_offset(0.0); + set_goal_view_tilt(0.0); #ifdef NO_SMOOTH_MOUSE_VIEW set_view_offset(0.0); + set_view_tilt(0.0); #endif // NO_SMOOTH_MOUSE_VIEW #endif // RESET_VIEW_ON_LEAVING_MOUSE_VIEW glutSetCursor(GLUT_CURSOR_INHERIT); @@ -646,3 +663,5 @@ void guiMouseFunc(int button, int updown, int x, int y) glutPostRedisplay (); } + + diff --git a/src/Main/Makefile.am b/src/Main/Makefile.am index 6324e2245..84feff63b 100644 --- a/src/Main/Makefile.am +++ b/src/Main/Makefile.am @@ -52,8 +52,6 @@ fgfs_SOURCES = \ options.cxx options.hxx \ splash.cxx splash.hxx \ viewer.cxx viewer.hxx \ - viewer_lookat.cxx viewer_lookat.hxx \ - viewer_rph.cxx viewer_rph.hxx \ viewmgr.cxx viewmgr.hxx fgfs_LDADD = \ @@ -95,3 +93,4 @@ INCLUDES += -I$(top_srcdir) -I$(top_srcdir)/src else INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src endif + diff --git a/src/Main/fg_commands.cxx b/src/Main/fg_commands.cxx index 83eedd9fe..9dac586d5 100644 --- a/src/Main/fg_commands.cxx +++ b/src/Main/fg_commands.cxx @@ -242,7 +242,7 @@ do_preferences_load (const SGPropertyNode * arg, SGCommandState ** state) static bool do_view_cycle (const SGPropertyNode * arg, SGCommandState ** state) { - globals->get_current_view()->set_view_offset(0.0); + globals->get_current_view()->setHeadingOffset_deg(0.0); globals->get_viewmgr()->next_view(); if ( fgGetString("/sim/flight-model") == "ada" ) { globals->get_props()->setBoolValue( "/sim/hud/visibility", true ); @@ -605,3 +605,4 @@ fgInitCommands () } // end of fg_commands.hxx + diff --git a/src/Main/model.cxx b/src/Main/model.cxx index 8016f97ca..d4d8b9975 100644 --- a/src/Main/model.cxx +++ b/src/Main/model.cxx @@ -159,8 +159,8 @@ FGAircraftModel::update (int dt) do_animation(_animations[i], elapsed_ms); _selector->select(true); - FGViewerRPH *pilot_view = - (FGViewerRPH *)globals->get_viewmgr()->get_view( 0 ); + FGViewer *pilot_view = + (FGViewer *)globals->get_viewmgr()->get_view( 0 ); sgMat4 sgTRANS; sgMakeTransMat4( sgTRANS, pilot_view->get_view_pos() ); @@ -178,15 +178,13 @@ FGAircraftModel::update (int dt) if (view_number == 0) { // FIXME: orientation is not applied // correctly when view is not forward - sgMakeRotMat4( sgROT, -pilot_view->get_view_offset() - * SGD_RADIANS_TO_DEGREES, pilot_view->get_world_up() ); + sgMakeRotMat4( sgROT, -pilot_view->getHeadingOffset_deg(), + pilot_view->get_world_up() ); /* Warning lame hack from Wilson ahead */ /* get the pitch value */ - sgVec3 rph; - sgCopyVec3(rph, pilot_view->get_rph()); /* double it to counter the value already in the VIEW_ROT */ - float pitch = rph[1] * 2; + float pitch = pilot_view->getPitch_deg() * SGD_DEGREES_TO_RADIANS * 2; /* make a ROT matrix with the values waited by the X coordinate from the offset rotation see sgROT above @@ -383,3 +381,7 @@ FGAircraftModel::Animation::setRotation() // end of model.cxx + + + + diff --git a/src/Main/options.cxx b/src/Main/options.cxx index 5ae407cd9..4d72d4101 100644 --- a/src/Main/options.cxx +++ b/src/Main/options.cxx @@ -882,11 +882,11 @@ parse_option (const string& arg) } else { default_view_offset = atof( woffset.c_str() ) * SGD_DEGREES_TO_RADIANS; } - FGViewerRPH *pilot_view = - (FGViewerRPH *)globals->get_viewmgr()->get_view( 0 ); - pilot_view->set_view_offset( default_view_offset ); - pilot_view->set_goal_view_offset( default_view_offset ); - fgSetDouble("/sim/view/offset-deg", default_view_offset); + FGViewer *pilot_view = + (FGViewer *)globals->get_viewmgr()->get_view( 0 ); + pilot_view->setHeadingOffset_deg( default_view_offset * SGD_RADIANS_TO_DEGREES ); + pilot_view->set_goal_view_offset( default_view_offset * SGD_RADIANS_TO_DEGREES ); + fgSetDouble("/sim/view/offset-deg", default_view_offset * SGD_RADIANS_TO_DEGREES ); // $$$ end - added VS Renganathan, 14 Oct 2K } else if ( arg.find( "--visibility=" ) == 0 ) { fgSetDouble("/environment/visibility-m", atof(arg.substr(13))); @@ -1297,3 +1297,5 @@ fgUsage () << " instances allowed." << endl << endl; } + + diff --git a/src/Main/viewer.cxx b/src/Main/viewer.cxx index 2628efc8f..1cdb8eb10 100644 --- a/src/Main/viewer.cxx +++ b/src/Main/viewer.cxx @@ -2,6 +2,8 @@ // // Written by Curtis Olson, started August 1997. // overhaul started October 2000. +// partially rewritten by Jim Wilson jim@kelcomaine.com using interface +// by David Megginson March 2002 // // Copyright (C) 1997 - 2000 Curtis L. Olson - curt@flightgear.org // @@ -36,99 +38,13 @@ #include +/* from lookat */ +#include +#include "globals.hxx" +/* end from lookat */ + #include "viewer.hxx" - - -//////////////////////////////////////////////////////////////////////// -// Implementation of FGViewPoint. -//////////////////////////////////////////////////////////////////////// - -FGViewPoint::FGViewPoint () - : _dirty(true), - _lon_deg(0), - _lat_deg(0), - _alt_ft(0) -{ -} - -FGViewPoint::~FGViewPoint () -{ -} - -void -FGViewPoint::setPosition (double lon_deg, double lat_deg, double alt_ft) -{ - _dirty = true; - _lon_deg = lon_deg; - _lat_deg = lat_deg; - _alt_ft = alt_ft; -} - -const double * -FGViewPoint::getAbsoluteViewPos () const -{ - if (_dirty) - recalc(); - return _absolute_view_pos; -} - -const float * -FGViewPoint::getRelativeViewPos () const -{ - if (_dirty) - recalc(); - return _relative_view_pos; -} - -const float * -FGViewPoint::getZeroElevViewPos () const -{ - if (_dirty) - recalc(); - return _zero_elev_view_pos; -} - -void -FGViewPoint::recalc () const -{ - double sea_level_radius_m; - double lat_geoc_rad; - - // Convert from geodetic to geocentric - // coordinates. - sgGeodToGeoc(_lat_deg * SGD_DEGREES_TO_RADIANS, - _alt_ft * SG_FEET_TO_METER, - &sea_level_radius_m, - &lat_geoc_rad); - - // Calculate the cartesian coordinates - // of point directly below at sea level. - Point3D p = Point3D(_lon_deg * SG_DEGREES_TO_RADIANS, - lat_geoc_rad, - sea_level_radius_m); - Point3D tmp = sgPolarToCart3d(p) - scenery.get_next_center(); - sgSetVec3(_zero_elev_view_pos, tmp[0], tmp[1], tmp[2]); - - // Calculate the absolute view position - // in fgfs coordinates. - p.setz(p.radius() + _alt_ft * SG_FEET_TO_METER); - tmp = sgPolarToCart3d(p); - sgdSetVec3(_absolute_view_pos, tmp[0], tmp[1], tmp[2]); - - // Calculate the relative view position - // from the scenery center. - sgdVec3 scenery_center; - sgdSetVec3(scenery_center, - scenery.get_next_center().x(), - scenery.get_next_center().y(), - scenery.get_next_center().z()); - sgdVec3 view_pos; - sgdSubVec3(view_pos, _absolute_view_pos, scenery_center); - sgSetVec3(_relative_view_pos, view_pos); -} - - //////////////////////////////////////////////////////////////////////// // Implementation of FGViewer. @@ -138,14 +54,26 @@ FGViewPoint::recalc () const FGViewer::FGViewer( void ): scalingType(FG_SCALING_MAX), fov(55.0), - view_offset(0.0), goal_view_offset(0.0), - view_tilt(0.0), - goal_view_tilt(0.0) + goal_view_tilt(0.0), + _dirty(true), + _lon_deg(0), + _lat_deg(0), + _alt_ft(0), + _target_lon_deg(0), + _target_lat_deg(0), + _target_alt_ft(0), + _roll_deg(0), + _pitch_deg(0), + _heading_deg(0), + _x_offset_m(0), + _y_offset_m(0), + _z_offset_m(0), + _heading_offset_deg(0), + _pitch_offset_deg(0), + _roll_offset_deg(0) { - sgSetVec3( pilot_offset, 0.0, 0.0, 0.0 ); - sgdZeroVec3(geod_view_pos); - sgdZeroVec3(abs_view_pos); + sgdZeroVec3(_absolute_view_pos); sea_level_radius = SG_EQUATORIAL_RADIUS_M; //a reasonable guess for init, so that the math doesn't blow up } @@ -158,6 +86,13 @@ FGViewer::~FGViewer( void ) { void FGViewer::init () { + if ( _type == FG_LOOKAT ) { + set_reverse_view_offset(true); + } + + if ( _type == FG_RPH ) { + set_reverse_view_offset(false); + } } void @@ -170,6 +105,369 @@ FGViewer::unbind () { } +void +FGViewer::setType ( int type ) +{ + if (type == 0) + _type = FG_RPH; + if (type == 1) + _type = FG_LOOKAT; +} + +void +FGViewer::setLongitude_deg (double lon_deg) +{ + _dirty = true; + _lon_deg = lon_deg; +} + +void +FGViewer::setLatitude_deg (double lat_deg) +{ + _dirty = true; + _lat_deg = lat_deg; +} + +void +FGViewer::setAltitude_ft (double alt_ft) +{ + _dirty = true; + _alt_ft = alt_ft; +} + +void +FGViewer::setPosition (double lon_deg, double lat_deg, double alt_ft) +{ + _dirty = true; + _lon_deg = lon_deg; + _lat_deg = lat_deg; + _alt_ft = alt_ft; +} + +void +FGViewer::setTargetLongitude_deg (double lon_deg) +{ + _dirty = true; + _target_lon_deg = lon_deg; +} + +void +FGViewer::setTargetLatitude_deg (double lat_deg) +{ + _dirty = true; + _target_lat_deg = lat_deg; +} + +void +FGViewer::setTargetAltitude_ft (double alt_ft) +{ + _dirty = true; + _target_alt_ft = alt_ft; +} + +void +FGViewer::setTargetPosition (double lon_deg, double lat_deg, double alt_ft) +{ + _dirty = true; + _target_lon_deg = lon_deg; + _target_lat_deg = lat_deg; + _target_alt_ft = alt_ft; +} + +void +FGViewer::setRoll_deg (double roll_deg) +{ + _dirty = true; + _roll_deg = roll_deg; +} + +void +FGViewer::setPitch_deg (double pitch_deg) +{ + _dirty = true; + _pitch_deg = pitch_deg; +} + +void +FGViewer::setHeading_deg (double heading_deg) +{ + _dirty = true; + _heading_deg = heading_deg; +} + +void +FGViewer::setOrientation (double roll_deg, double pitch_deg, double heading_deg) +{ + _dirty = true; + _roll_deg = roll_deg; + _pitch_deg = pitch_deg; + _heading_deg = heading_deg; +} + +void +FGViewer::setXOffset_m (double x_offset_m) +{ + _dirty = true; + _x_offset_m = x_offset_m; +} + +void +FGViewer::setYOffset_m (double y_offset_m) +{ + _dirty = true; + _y_offset_m = y_offset_m; +} + +void +FGViewer::setZOffset_m (double z_offset_m) +{ + _dirty = true; + _z_offset_m = z_offset_m; +} + +void +FGViewer::setPositionOffsets (double x_offset_m, double y_offset_m, double z_offset_m) +{ + _dirty = true; + _x_offset_m = x_offset_m; + _y_offset_m = y_offset_m; + _z_offset_m = z_offset_m; +} + +void +FGViewer::setRollOffset_deg (double roll_offset_deg) +{ + _dirty = true; + _roll_offset_deg = roll_offset_deg; +} + +void +FGViewer::setPitchOffset_deg (double pitch_offset_deg) +{ + _dirty = true; + _pitch_offset_deg = pitch_offset_deg; +} + +void +FGViewer::setHeadingOffset_deg (double heading_offset_deg) +{ + _dirty = true; + _heading_offset_deg = heading_offset_deg; +} + +void +FGViewer::setOrientationOffsets (double roll_offset_deg, double pitch_offset_deg, double heading_offset_deg) +{ + _dirty = true; + _roll_offset_deg = roll_offset_deg; + _pitch_offset_deg = pitch_offset_deg; + _heading_offset_deg = heading_offset_deg; +} + +double * +FGViewer::get_absolute_view_pos () +{ + if (_dirty) + recalc(); + return _absolute_view_pos; +} + +float * +FGViewer::getRelativeViewPos () +{ + if (_dirty) + recalc(); + return _relative_view_pos; +} + +float * +FGViewer::getZeroElevViewPos () +{ + if (_dirty) + recalc(); + return _zero_elev_view_pos; +} + + +// recalc() is done every time one of the setters is called (making the +// cached data "dirty"). It calculates all the outputs for viewer. +void +FGViewer::recalc () +{ + sgVec3 minus_z, right, forward, tilt; + sgMat4 VIEWo; + sgMat4 tmpROT; // temp rotation work matrices + sgVec3 tmpVec3; // temp work vector (3) + + + // The position vectors originate from the view point or target location + // depending on the type of view. + + if (_type == FG_RPH) { + recalcPositionVectors( _lon_deg, _lat_deg, _alt_ft ); + } else { + recalcPositionVectors( _target_lon_deg, _target_lat_deg, _target_alt_ft ); + } + + sgCopyVec3(zero_elev, _zero_elev_view_pos); + sgCopyVec3(view_pos, _relative_view_pos); + + if (_type == FG_LOOKAT) { + + // Make the world up rotation matrix for lookat + sgMakeRotMat4( UP, _target_lon_deg, 0.0, -_target_lat_deg ); + + // get the world up verctor from the worldup rotation matrix + sgSetVec3( world_up, UP[0][0], UP[0][1], UP[0][2] ); + + sgCopyVec3( view_up, world_up ); + + + // create offset vector + sgVec3 lookat_offset; + sgSetVec3( lookat_offset, _x_offset_m, _y_offset_m, _z_offset_m ); + + // Apply heading orientation and orientation offset to lookat_offset... + sgMakeRotMat4( tmpROT, _heading_offset_deg -_heading_deg, world_up); + sgXformVec3( lookat_offset, lookat_offset, UP ); + sgXformVec3( lookat_offset, lookat_offset, tmpROT ); + + // Apply orientation offset tilt... + // FIXME: Need to get and use a "right" vector instead of 1-0-0 + sgSetVec3 (tmpVec3, 1, 0, 0); + sgMakeRotMat4( tmpROT, _pitch_offset_deg, tmpVec3 ); + sgXformPnt3( lookat_offset, lookat_offset, tmpROT ); + + // add the offsets including rotations to the coordinates + sgAddVec3( view_pos, lookat_offset ); + + // Make the VIEW matrix. + fgMakeLookAtMat4( VIEW, view_pos, view_forward, view_up ); + + + // the VIEW matrix includes both rotation and translation. Let's + // knock out the translation part to make the VIEW_ROT matrix + sgCopyMat4( VIEW_ROT, VIEW ); + VIEW_ROT[3][0] = VIEW_ROT[3][1] = VIEW_ROT[3][2] = 0.0; + + } + + if (_type == FG_RPH) { + + // code to calculate LOCAL matrix calculated from Phi, Theta, and + // Psi (roll, pitch, yaw) in case we aren't running LaRCsim as our + // flight model + + fgMakeLOCAL( LOCAL, _pitch_deg * SG_DEGREES_TO_RADIANS, + _roll_deg * SG_DEGREES_TO_RADIANS, + -_heading_deg * SG_DEGREES_TO_RADIANS); + + // Make the world up rotation matrix for pilot view + sgMakeRotMat4( UP, _lon_deg, 0.0, -_lat_deg ); + + // get the world up verctor from the worldup rotation matrix + sgSetVec3( world_up, UP[0][0], UP[0][1], UP[0][2] ); + + // VIEWo becomes the rotation matrix with world_up incorporated + sgCopyMat4( VIEWo, LOCAL ); + sgPostMultMat4( VIEWo, UP ); + + // generate the sg view up and forward vectors + sgSetVec3( view_up, VIEWo[0][0], VIEWo[0][1], VIEWo[0][2] ); + sgSetVec3( right, VIEWo[1][0], VIEWo[1][1], VIEWo[1][2] ); + sgSetVec3( forward, VIEWo[2][0], VIEWo[2][1], VIEWo[2][2] ); + + // apply the offsets in world coordinates + sgVec3 pilot_offset_world; + sgSetVec3( pilot_offset_world, + _z_offset_m, _y_offset_m, -_x_offset_m ); + sgXformVec3( pilot_offset_world, pilot_offset_world, VIEWo ); + + // generate the view offset matrix using orientation offset (heading) + sgMakeRotMat4( VIEW_OFFSET, _heading_offset_deg, view_up ); + + // create a tilt matrix using orientation offset (pitch) + sgMat4 VIEW_TILT; + sgMakeRotMat4( VIEW_TILT, _pitch_offset_deg, right ); + sgPreMultMat4(VIEW_OFFSET, VIEW_TILT); + sgXformVec3( view_forward, forward, VIEW_OFFSET ); + SG_LOG( SG_VIEW, SG_DEBUG, "(RPH) view forward = " + << view_forward[0] << "," << view_forward[1] << "," + << view_forward[2] ); + + // VIEW_ROT = LARC_TO_SSG * ( VIEWo * VIEW_OFFSET ) + fgMakeViewRot( VIEW_ROT, VIEW_OFFSET, VIEWo ); + + sgVec3 trans_vec; + sgAddVec3( trans_vec, view_pos, pilot_offset_world ); + + // VIEW = VIEW_ROT * TRANS + sgCopyMat4( VIEW, VIEW_ROT ); + sgPostMultMat4ByTransMat4( VIEW, trans_vec ); + + } + + // Given a vector pointing straight down (-Z), map into onto the + // local plane representing "horizontal". This should give us the + // local direction for moving "south". + sgSetVec3( minus_z, 0.0, 0.0, -1.0 ); + + sgmap_vec_onto_cur_surface_plane(world_up, view_pos, minus_z, + surface_south); + sgNormalizeVec3(surface_south); + + // now calculate the surface east vector + sgVec3 world_down; + sgNegateVec3(world_down, world_up); + sgVectorProductVec3(surface_east, surface_south, world_down); + + set_clean(); +} + +void +FGViewer::recalcPositionVectors (double lon_deg, double lat_deg, double alt_ft) const +{ + double sea_level_radius_m; + double lat_geoc_rad; + + + // Convert from geodetic to geocentric + // coordinates. + sgGeodToGeoc(lat_deg * SGD_DEGREES_TO_RADIANS, + alt_ft * SG_FEET_TO_METER, + &sea_level_radius_m, + &lat_geoc_rad); + + // Calculate the cartesian coordinates + // of point directly below at sea level. + // aka Zero Elevation Position + Point3D p = Point3D(lon_deg * SG_DEGREES_TO_RADIANS, + lat_geoc_rad, + sea_level_radius_m); + Point3D tmp = sgPolarToCart3d(p) - scenery.get_next_center(); + sgSetVec3(_zero_elev_view_pos, tmp[0], tmp[1], tmp[2]); + + // Calculate the absolute view position + // in fgfs coordinates. + // aka Absolute View Position + p.setz(p.radius() + alt_ft * SG_FEET_TO_METER); + tmp = sgPolarToCart3d(p); + sgdSetVec3(_absolute_view_pos, tmp[0], tmp[1], tmp[2]); + + // Calculate the relative view position + // from the scenery center. + // aka Relative View Position + sgdVec3 scenery_center; + sgdSetVec3(scenery_center, + scenery.get_next_center().x(), + scenery.get_next_center().y(), + scenery.get_next_center().z()); + sgdVec3 view_pos; + sgdSubVec3(view_pos, _absolute_view_pos, scenery_center); + sgSetVec3(_relative_view_pos, view_pos); + +} + double FGViewer::get_h_fov() { @@ -216,60 +514,164 @@ FGViewer::update (int dt) { int i; for ( i = 0; i < dt; i++ ) { - if ( fabs(get_goal_view_offset() - get_view_offset()) < 0.05 ) { - set_view_offset( get_goal_view_offset() ); + if ( fabs(get_goal_view_offset() - getHeadingOffset_deg()) < 1 ) { + setHeadingOffset_deg( get_goal_view_offset() ); break; } else { - // move current_view.view_offset towards + // move current_view.headingoffset towards // current_view.goal_view_offset - if ( get_goal_view_offset() > get_view_offset() ) + if ( get_goal_view_offset() > getHeadingOffset_deg() ) { - if ( get_goal_view_offset() - get_view_offset() < SGD_PI ){ - inc_view_offset( 0.01 ); + if ( get_goal_view_offset() - getHeadingOffset_deg() < 180 ){ + inc_view_offset( 0.5 ); } else { - inc_view_offset( -0.01 ); + inc_view_offset( -0.5 ); } } else { - if ( get_view_offset() - get_goal_view_offset() < SGD_PI ){ - inc_view_offset( -0.01 ); + if ( getHeadingOffset_deg() - get_goal_view_offset() < 180 ){ + inc_view_offset( -0.5 ); } else { - inc_view_offset( 0.01 ); + inc_view_offset( 0.5 ); } } - if ( get_view_offset() > SGD_2PI ) { - inc_view_offset( -SGD_2PI ); - } else if ( get_view_offset() < 0 ) { - inc_view_offset( SGD_2PI ); + if ( getHeadingOffset_deg() > 360 ) { + inc_view_offset( -360 ); + } else if ( getHeadingOffset_deg() < 0 ) { + inc_view_offset( 360 ); } } } for ( i = 0; i < dt; i++ ) { - if ( fabs(get_goal_view_tilt() - get_view_tilt()) < 0.05 ) { - set_view_tilt( get_goal_view_tilt() ); + if ( fabs(get_goal_view_tilt() - getPitchOffset_deg()) < 1 ) { + setPitchOffset_deg( get_goal_view_tilt() ); break; } else { - // move current_view.view_tilt towards + // move current_view.pitch_offset_deg towards // current_view.goal_view_tilt - if ( get_goal_view_tilt() > get_view_tilt() ) + if ( get_goal_view_tilt() > getPitchOffset_deg() ) { - if ( get_goal_view_tilt() - get_view_tilt() < SGD_PI ){ - inc_view_tilt( 0.01 ); + if ( get_goal_view_tilt() - getPitchOffset_deg() < 0 ){ + inc_view_tilt( 1.0 ); } else { - inc_view_tilt( -0.01 ); + inc_view_tilt( -1.0 ); } } else { - if ( get_view_tilt() - get_goal_view_tilt() < SGD_PI ){ - inc_view_tilt( -0.01 ); + if ( getPitchOffset_deg() - get_goal_view_tilt() < 0 ){ + inc_view_tilt( -1.0 ); } else { - inc_view_tilt( 0.01 ); + inc_view_tilt( 1.0 ); } } - if ( get_view_tilt() > SGD_2PI ) { - inc_view_tilt( -SGD_2PI ); - } else if ( get_view_tilt() < 0 ) { - inc_view_tilt( SGD_2PI ); + if ( getPitchOffset_deg() > 90 ) { + setPitchOffset_deg(90); + } else if ( getPitchOffset_deg() < -90 ) { + setPitchOffset_deg( -90 ); } } } } + + +void FGViewer::fgMakeLookAtMat4 ( sgMat4 dst, const sgVec3 eye, const sgVec3 center, + const sgVec3 up ) +{ + // Caveats: + // 1) In order to compute the line of sight, the eye point must not be equal + // to the center point. + // 2) The up vector must not be parallel to the line of sight from the eye + // to the center point. + + /* Compute the direction vectors */ + sgVec3 x,y,z; + + /* Y vector = center - eye */ + sgSubVec3 ( y, center, eye ) ; + + /* Z vector = up */ + sgCopyVec3 ( z, up ) ; + + /* X vector = Y cross Z */ + sgVectorProductVec3 ( x, y, z ) ; + + /* Recompute Z = X cross Y */ + sgVectorProductVec3 ( z, x, y ) ; + + /* Normalize everything */ + sgNormaliseVec3 ( x ) ; + sgNormaliseVec3 ( y ) ; + sgNormaliseVec3 ( z ) ; + + /* Build the matrix */ +#define M(row,col) dst[row][col] + M(0,0) = x[0]; M(0,1) = x[1]; M(0,2) = x[2]; M(0,3) = 0.0; + M(1,0) = y[0]; M(1,1) = y[1]; M(1,2) = y[2]; M(1,3) = 0.0; + M(2,0) = z[0]; M(2,1) = z[1]; M(2,2) = z[2]; M(2,3) = 0.0; + M(3,0) = eye[0]; M(3,1) = eye[1]; M(3,2) = eye[2]; M(3,3) = 1.0; +#undef M +} +/* end from lookat */ + +/* from rph */ +// VIEW_ROT = LARC_TO_SSG * ( VIEWo * VIEW_OFFSET ) +// This takes advantage of the fact that VIEWo and VIEW_OFFSET +// only have entries in the upper 3x3 block +// and that LARC_TO_SSG is just a shift of rows NHV +void FGViewer::fgMakeViewRot( sgMat4 dst, const sgMat4 m1, const sgMat4 m2 ) +{ + for ( int j = 0 ; j < 3 ; j++ ) { + dst[2][j] = m2[0][0] * m1[0][j] + + m2[0][1] * m1[1][j] + + m2[0][2] * m1[2][j]; + + dst[0][j] = m2[1][0] * m1[0][j] + + m2[1][1] * m1[1][j] + + m2[1][2] * m1[2][j]; + + dst[1][j] = m2[2][0] * m1[0][j] + + m2[2][1] * m1[1][j] + + m2[2][2] * m1[2][j]; + } + dst[0][3] = + dst[1][3] = + dst[2][3] = + dst[3][0] = + dst[3][1] = + dst[3][2] = SG_ZERO; + dst[3][3] = SG_ONE; +} + + +void FGViewer::fgMakeLOCAL( sgMat4 dst, const double Theta, + const double Phi, const double Psi) +{ + SGfloat cosTheta = (SGfloat) cos(Theta); + SGfloat sinTheta = (SGfloat) sin(Theta); + SGfloat cosPhi = (SGfloat) cos(Phi); + SGfloat sinPhi = (SGfloat) sin(Phi); + SGfloat sinPsi = (SGfloat) sin(Psi) ; + SGfloat cosPsi = (SGfloat) cos(Psi) ; + + dst[0][0] = cosPhi * cosTheta; + dst[0][1] = sinPhi * cosPsi + cosPhi * -sinTheta * -sinPsi; + dst[0][2] = sinPhi * sinPsi + cosPhi * -sinTheta * cosPsi; + dst[0][3] = SG_ZERO; + + dst[1][0] = -sinPhi * cosTheta; + dst[1][1] = cosPhi * cosPsi + -sinPhi * -sinTheta * -sinPsi; + dst[1][2] = cosPhi * sinPsi + -sinPhi * -sinTheta * cosPsi; + dst[1][3] = SG_ZERO ; + + dst[2][0] = sinTheta; + dst[2][1] = cosTheta * -sinPsi; + dst[2][2] = cosTheta * cosPsi; + dst[2][3] = SG_ZERO; + + dst[3][0] = SG_ZERO; + dst[3][1] = SG_ZERO; + dst[3][2] = SG_ZERO; + dst[3][3] = SG_ONE ; +} + +/* end from rph */ + diff --git a/src/Main/viewer.hxx b/src/Main/viewer.hxx index 7c1a5e58d..c7bae2d4b 100644 --- a/src/Main/viewer.hxx +++ b/src/Main/viewer.hxx @@ -2,6 +2,8 @@ // // Written by Curtis Olson, started August 1997. // overhaul started October 2000. +// partially rewritten by Jim Wilson jim@kelcomaine.com using interface +// by David Megginson March 2002 // // Copyright (C) 1997 - 2000 Curtis L. Olson - curt@flightgear.org // @@ -42,73 +44,8 @@ #define FG_FOV_MAX 179.9 -/** - * Representation of a single viewpoint in the FlightGear world. - */ -class FGViewPoint -{ -public: - FGViewPoint (); - virtual ~FGViewPoint (); - - /** - * Set the geodetic position for the view point. - */ - virtual void setPosition (double lon_deg, double lat_deg, double alt_ft); - - - /** - * Get the longitude in degrees. - */ - virtual double getLongitude_deg () const { return _lon_deg; } - - /** - * Get the latitude in degrees. - */ - virtual double getLatitude_deg () const { return _lat_deg; } - - /** - * Get the altitude in feet ASL. - */ - virtual double getAltitudeASL_ft () const { return _alt_ft; } - - /** - * Get the absolute view position in fgfs coordinates. - */ - virtual const double * getAbsoluteViewPos () const; - - - /** - * Get the relative view position in fgfs coordinates. - * - * The position is relative to the scenery centre. - */ - virtual const float * getRelativeViewPos () const; - - - /** - * Get the absolute zero-elevation view position in fgfs coordinates. - */ - virtual const float * getZeroElevViewPos () const; - -private: - - void recalc () const; - - mutable sgdVec3 _absolute_view_pos; - mutable sgVec3 _relative_view_pos; - mutable sgVec3 _zero_elev_view_pos; - - bool _dirty; - double _lon_deg; - double _lat_deg; - double _alt_ft; - -}; - - // Define a structure containing view information -class FGViewer { +class FGViewer : public FGSubsystem { public: @@ -125,42 +62,168 @@ public: // FG_SCALING_INDEPENDENT // whole screen }; + // Constructor + FGViewer( void ); + + // Destructor + virtual ~FGViewer( void ); + + ////////////////////////////////////////////////////////////////////// + // Part 1: standard FGSubsystem implementation. + ////////////////////////////////////////////////////////////////////// + + virtual void init (); + virtual void bind (); + virtual void unbind (); + void update (int dt); + + + ////////////////////////////////////////////////////////////////////// + // Part 2: user settings. + ////////////////////////////////////////////////////////////////////// + + virtual fgViewType getType() const { return _type; } + virtual void setType( int type ); + + // Reference geodetic position of view from position... + virtual double getLongitude_deg () const { return _lon_deg; } + virtual double getLatitude_deg () const { return _lat_deg; } + virtual double getAltitudeASL_ft () const { return _alt_ft; } + // Set individual coordinates for the view point position. + virtual void setLongitude_deg (double lon_deg); + virtual void setLatitude_deg (double lat_deg); + virtual void setAltitude_ft (double alt_ft); + // Set the geodetic position for the view point. + virtual void setPosition (double lon_deg, double lat_deg, double alt_ft); + + // Reference geodetic target position... + virtual double getTargetLongitude_deg () const { return _target_lon_deg; } + virtual double getTargetLatitude_deg () const { return _target_lat_deg; } + virtual double getTargetAltitudeASL_ft () const { return _target_alt_ft; } + // Set individual coordinates for the Target point position. + virtual void setTargetLongitude_deg (double lon_deg); + virtual void setTargetLatitude_deg (double lat_deg); + virtual void setTargetAltitude_ft (double alt_ft); + // Set the geodetic position for the Target point. + virtual void setTargetPosition (double lon_deg, double lat_deg, double alt_ft); + + // Refence orientation... + virtual double getRoll_deg () const { return _roll_deg; } + virtual double getPitch_deg () const {return _pitch_deg; } + virtual double getHeading_deg () const {return _heading_deg; } + virtual void setRoll_deg (double roll_deg); + virtual void setPitch_deg (double pitch_deg); + virtual void setHeading_deg (double heading_deg); + virtual void setOrientation (double roll_deg, double pitch_deg, double heading_deg); + + // Position offsets from reference + virtual double getXOffset_m () const { return _x_offset_m; } + virtual double getYOffset_m () const { return _y_offset_m; } + virtual double getZOffset_m () const { return _z_offset_m; } + virtual void setXOffset_m (double x_offset_m); + virtual void setYOffset_m (double y_offset_m); + virtual void setZOffset_m (double z_offset_m); + virtual void setPositionOffsets (double x_offset_m, + double y_offset_m, + double z_offset_m); + + // Orientation offsets from reference + virtual double getRollOffset_deg () const { return _roll_offset_deg; } + virtual double getPitchOffset_deg () const { return _pitch_offset_deg; } + virtual double getHeadingOffset_deg () const { return _heading_offset_deg; } + virtual void setRollOffset_deg (double roll_offset_deg); + virtual void setPitchOffset_deg (double pitch_offset_deg); + virtual void setHeadingOffset_deg (double heading_offset_deg); + virtual void setOrientationOffsets (double roll_offset_deg, + double heading_offset_deg, + double pitch_offset_deg); + + + + ////////////////////////////////////////////////////////////////////// + // Part 3: output vectors and matrices in FlightGear coordinates. + ////////////////////////////////////////////////////////////////////// + + // Vectors and positions... + + // Get zero view_pos + virtual float * get_view_pos() {if ( _dirty ) { recalc(); } return view_pos; } + // Get the absolute view position in fgfs coordinates. + virtual double * get_absolute_view_pos (); + // Get zero elev + virtual float * get_zero_elev() {if ( _dirty ) { recalc(); } return zero_elev; } + // Get world up vector + virtual float *get_world_up() {if ( _dirty ) { recalc(); } return world_up; } + // Get the relative (to scenery center) view position in fgfs coordinates. + virtual float * getRelativeViewPos (); + // Get the absolute zero-elevation view position in fgfs coordinates. + virtual float * getZeroElevViewPos (); + // Get surface east vector + virtual float *get_surface_east() { if ( _dirty ) { recalc(); } return surface_east; } + // Get surface south vector + virtual float *get_surface_south() {if ( _dirty ) { recalc(); } return surface_south; } + + // Matrices... + virtual const sgVec4 *get_VIEW() { if ( _dirty ) { recalc(); } return VIEW; } + virtual const sgVec4 *get_VIEW_ROT() { if ( _dirty ) { recalc(); } return VIEW_ROT; } + virtual const sgVec4 *get_UP() { if ( _dirty ) { recalc(); } return UP; } + // (future?) + // virtual double get_ground_elev() { if ( _dirty ) { recalc(); } return ground_elev; } + + private: // flag forcing a recalc of derived view parameters - bool dirty; + bool _dirty; + + void recalc (); + void recalcPositionVectors (double lon_deg, double lat_deg, double alt_ft) const; + + mutable sgdVec3 _absolute_view_pos; + mutable sgVec3 _relative_view_pos; + mutable sgVec3 _zero_elev_view_pos; + + double _lon_deg; + double _lat_deg; + double _alt_ft; + double _target_lon_deg; + double _target_lat_deg; + double _target_alt_ft; + + double _roll_deg; + double _pitch_deg; + double _heading_deg; + + // Position offsets from center of gravity. The X axis is positive + // out the tail, Y is out the right wing, and Z is positive up. + // distance in meters + double _x_offset_m; + double _y_offset_m; + double _z_offset_m; + + // orientation offsets from reference + double _roll_offset_deg; + double _pitch_offset_deg; + double _heading_offset_deg; protected: fgViewType _type; fgScalingType scalingType; - FGViewPoint view_point; - // the nominal field of view (angle, in degrees) double fov; // ratio of window width and height; height = width * aspect_ratio double aspect_ratio; - // the current view offset angle from forward (rotated about the - // view_up vector) - double view_offset; bool reverse_view_offset; // 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; - - // absolute view position in earth coordinates - sgdVec3 abs_view_pos; - // view position in opengl world coordinates (this is the // abs_view_pos translated to scenery.center) sgVec3 view_pos; @@ -175,11 +238,6 @@ protected: // height ASL of the terrain for our current view position // (future?) double ground_elev; - // pilot offset from center of gravity. The X axis is positive - // out the tail, Y is out the right wing, and Z is positive up. - // Distances in meters of course. - sgVec3 pilot_offset; - // surface vector heading south sgVec3 surface_south; @@ -194,24 +252,35 @@ protected: // sg versions of our friendly matrices sgMat4 VIEW, VIEW_ROT, UP; - inline void set_dirty() { dirty = true; } - inline void set_clean() { dirty = false; } + // up vector for the view (usually point straight up through the + // top of the aircraft + sgVec3 view_up; + + // the vector pointing straight out the nose of the aircraft + sgVec3 view_forward; + + // Transformation matrix for the view direction offset relative to + // the AIRCRAFT matrix + sgMat4 VIEW_OFFSET; + + // sg versions of our friendly matrices (from lookat) + sgMat4 LOCAL, TRANS, LARC_TO_SSG; + + inline void set_dirty() { _dirty = true; } + inline void set_clean() { _dirty = false; } + + // from lookat + void fgMakeLookAtMat4 ( sgMat4 dst, const sgVec3 eye, const sgVec3 center, + const sgVec3 up ); + + // from rph + void fgMakeViewRot( sgMat4 dst, const sgMat4 m1, const sgMat4 m2 ); + void fgMakeLOCAL( sgMat4 dst, const double Theta, + const double Phi, const double Psi); - // Update the view volume, position, and orientation - virtual void update() = 0; public: - // Constructor - FGViewer( void ); - - // Destructor - virtual ~FGViewer( void ); - - virtual void init (); - virtual void bind (); - virtual void unbind (); - virtual void update (int dt); ////////////////////////////////////////////////////////////////////// // setter functions @@ -224,127 +293,81 @@ public: inline void set_aspect_ratio( double r ) { aspect_ratio = r; } - inline void set_view_offset( double a ) { - set_dirty(); - view_offset = a; - } inline void inc_view_offset( double amt ) { set_dirty(); - view_offset += amt; + _heading_offset_deg += amt; } inline void set_goal_view_offset( double a) { set_dirty(); goal_view_offset = a; while ( goal_view_offset < 0.0 ) { - goal_view_offset += SGD_2PI; + goal_view_offset += 360; } - while ( goal_view_offset > SGD_2PI ) { - goal_view_offset -= SGD_2PI; + while ( goal_view_offset > 360 ) { + goal_view_offset -= 360; } } 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; + _pitch_offset_deg += 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 < -90 ) { + goal_view_tilt = -90.0; } - while ( goal_view_tilt > 360.0 ) { - goal_view_tilt -= 360.0; + while ( goal_view_tilt > 90.0 ) { + goal_view_tilt = 90.0; } } - inline void set_geod_view_pos( double lon, double lat, double alt ) { - // data should be in radians and meters asl - set_dirty(); - // cout << "set_geod_view_pos = " << lon << ", " << lat << ", " << alt - // << endl; - sgdSetVec3( geod_view_pos, lon, lat, alt ); - } - inline void set_pilot_offset( float x, float y, float z ) { - set_dirty(); - sgSetVec3( pilot_offset, x, y, z ); - } inline void set_sea_level_radius( double r ) { // data should be in meters from the center of the earth set_dirty(); sea_level_radius = r; } + /* from lookat */ + inline void set_view_forward( sgVec3 vf ) { + set_dirty(); + sgCopyVec3( view_forward, vf ); + } + inline void set_view_up( sgVec3 vf ) { + set_dirty(); + sgCopyVec3( view_up, vf ); + } + /* end from lookat */ + + ////////////////////////////////////////////////////////////////////// // accessor functions ////////////////////////////////////////////////////////////////////// inline int get_type() const { return _type ; } inline int is_a( int t ) const { return get_type() == t ; } - inline bool is_dirty() const { return dirty; } + inline bool is_dirty() const { return _dirty; } inline double get_fov() const { return fov; } inline double get_aspect_ratio() const { return aspect_ratio; } - 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; } // Get horizontal field of view angle, in degrees. double get_h_fov(); // Get vertical field of view angle, in degrees. double get_v_fov(); + /* from lookat */ + inline float *get_view_forward() { return view_forward; } + inline float *get_view_up() { return view_up; } + /* end from lookat */ + ////////////////////////////////////////////////////////////////////// // derived values accessor functions ////////////////////////////////////////////////////////////////////// - inline double *get_abs_view_pos() { - if ( dirty ) { update(); } - return abs_view_pos; - } - inline float *get_view_pos() { - if ( dirty ) { update(); } - return view_pos; - } - inline float *get_zero_elev() { - if ( dirty ) { update(); } - return zero_elev; - } - // (future?) - // inline double get_ground_elev() { - // if ( dirty ) { update(); } - // return ground_elev; - // } - inline float *get_surface_south() { - if ( dirty ) { update(); } - return surface_south; - } - inline float *get_surface_east() { - if ( dirty ) { update(); } - return surface_east; - } - inline float *get_world_up() { - if ( dirty ) { update(); } - return world_up; - } - inline const sgVec4 *get_VIEW() { - if ( dirty ) { update(); } - return VIEW; - } - inline const sgVec4 *get_VIEW_ROT() { - if ( dirty ) { update(); } - return VIEW_ROT; - } - inline const sgVec4 *get_UP() { - if ( dirty ) { update(); } - return UP; - } + }; diff --git a/src/Main/viewmgr.cxx b/src/Main/viewmgr.cxx index 43921da9c..27410d4c4 100644 --- a/src/Main/viewmgr.cxx +++ b/src/Main/viewmgr.cxx @@ -1,6 +1,7 @@ // viewmgr.cxx -- class for managing all the views in the flightgear world. // // Written by Curtis Olson, started October 2000. +// partially rewritten by Jim Wilson March 2002 // // Copyright (C) 2000 Curtis L. Olson - curt@flightgear.org // @@ -44,8 +45,8 @@ FGViewMgr::~FGViewMgr( void ) { void FGViewMgr::init () { - add_view(new FGViewerRPH); - add_view(new FGViewerLookAt); + add_view(new FGViewer, 0); + add_view(new FGViewer, 1); } typedef double (FGViewMgr::*double_getter)() const; @@ -120,38 +121,44 @@ FGViewMgr::update (int dt) * SGD_DEGREES_TO_RADIANS; // Set up the pilot view - FGViewerRPH *pilot_view = (FGViewerRPH *)get_view( 0 ); - pilot_view ->set_geod_view_pos(lon_rad, lat_rad, alt_m); - pilot_view->set_rph(roll_rad, pitch_rad, heading_rad); + FGViewer *pilot_view = (FGViewer *)get_view( 0 ); + pilot_view ->setPosition( + fgGetDouble("/position/longitude-deg"), + fgGetDouble("/position/latitude-deg"), + fgGetDouble("/position/altitude-ft")); + pilot_view->setOrientation( + fgGetDouble("/orientation/roll-deg"), + fgGetDouble("/orientation/pitch-deg"), + fgGetDouble("/orientation/heading-deg")); if (fgGetString("/sim/flight-model") == "ada") { //+ve x is aft, +ve z is up (see viewer.hxx) - pilot_view->set_pilot_offset( -5.0, 0.0, 1.0 ); + pilot_view->setPositionOffsets( -5.0, 0.0, 1.0 ); } // Set up the chase view - // FIXME: the matrix math belongs in - // the viewer, not here. - FGViewerLookAt *chase_view = (FGViewerLookAt *)get_view( 1 ); + FGViewer *chase_view = (FGViewer *)get_view( 1 ); - sgVec3 po; // chase view pilot_offset - sgVec3 wup; // chase view world up - sgSetVec3( po, 0.0, 0.0, 100.0 ); - sgCopyVec3( wup, pilot_view->get_world_up() ); - sgMat4 CXFM; // chase view + pilot offset xform - sgMakeRotMat4( CXFM, - chase_view->get_view_offset() * SGD_RADIANS_TO_DEGREES - - heading_rad * SGD_RADIANS_TO_DEGREES, - wup ); - sgVec3 npo; // new pilot offset after rotation + // get xyz Position offsets directly from GUI/sgVec3Slider + // FIXME: change GUI/sgVec3Slider to store the xyz in properties + // it would probably be faster than the way PilotOffsetGet() + // triggers a recalc all the time. sgVec3 *pPO = PilotOffsetGet(); - sgXformVec3( po, *pPO, pilot_view->get_UP() ); - sgXformVec3( npo, po, CXFM ); + sgVec3 zPO; + sgCopyVec3( zPO, *pPO ); + chase_view->setPositionOffsets(zPO[0], zPO[1], zPO[2] ); - chase_view->set_geod_view_pos(lon_rad, lat_rad, alt_m); - chase_view->set_pilot_offset( npo[0], npo[1], npo[2] ); - chase_view->set_view_forward( pilot_view->get_view_pos() ); - chase_view->set_view_up( wup ); + chase_view->setOrientation( + fgGetDouble("/orientation/roll-deg"), + fgGetDouble("/orientation/pitch-deg"), + fgGetDouble("/orientation/heading-deg")); + + chase_view ->setTargetPosition( + fgGetDouble("/position/longitude-deg"), + fgGetDouble("/position/latitude-deg"), + fgGetDouble("/position/altitude-ft")); + chase_view->setPositionOffsets(zPO[0], zPO[1], zPO[2] ); + chase_view->set_view_forward( pilot_view->get_view_pos() ); // Update the current view do_axes(); @@ -162,7 +169,7 @@ double FGViewMgr::getViewOffset_deg () const { const FGViewer * view = get_current_view(); - return (view == 0 ? 0 : view->get_view_offset() * SGD_RADIANS_TO_DEGREES); + return (view == 0 ? 0 : view->getHeadingOffset_deg()); } void @@ -170,14 +177,14 @@ FGViewMgr::setViewOffset_deg (double offset) { FGViewer * view = get_current_view(); if (view != 0) - view->set_view_offset(offset * SGD_DEGREES_TO_RADIANS); + view->setHeadingOffset_deg(offset); } double FGViewMgr::getGoalViewOffset_deg () const { const FGViewer * view = get_current_view(); - return (view == 0 ? 0 : view->get_goal_view_offset() * SGD_RADIANS_TO_DEGREES); + return (view == 0 ? 0 : view->get_goal_view_offset()); } void @@ -185,14 +192,14 @@ FGViewMgr::setGoalViewOffset_deg (double offset) { FGViewer * view = get_current_view(); if (view != 0) - view->set_goal_view_offset(offset * SGD_DEGREES_TO_RADIANS); + view->set_goal_view_offset(offset); } double FGViewMgr::getViewTilt_deg () const { const FGViewer * view = get_current_view(); - return (view == 0 ? 0 : view->get_view_tilt() * SGD_RADIANS_TO_DEGREES); + return (view == 0 ? 0 : view->getPitchOffset_deg()); } void @@ -200,14 +207,14 @@ FGViewMgr::setViewTilt_deg (double tilt) { FGViewer * view = get_current_view(); if (view != 0) - view->set_view_tilt(tilt * SGD_DEGREES_TO_RADIANS); + view->setPitchOffset_deg(tilt); } double FGViewMgr::getGoalViewTilt_deg () const { const FGViewer * view = get_current_view(); - return (view == 0 ? 0 : view->get_goal_view_tilt() * SGD_RADIANS_TO_DEGREES); + return (view == 0 ? 0 : view->get_goal_view_tilt()); } void @@ -215,7 +222,7 @@ FGViewMgr::setGoalViewTilt_deg (double tilt) { FGViewer * view = get_current_view(); if (view != 0) - view->set_goal_view_tilt(tilt * SGD_DEGREES_TO_RADIANS); + view->set_goal_view_tilt(tilt); } double @@ -224,8 +231,7 @@ FGViewMgr::getPilotXOffset_m () const // FIXME: hard-coded pilot view position const FGViewer * pilot_view = get_view(0); if (pilot_view != 0) { - float * offset = ((FGViewer *)pilot_view)->get_pilot_offset(); - return offset[0]; + return ((FGViewer *)pilot_view)->getXOffset_m(); } else { return 0; } @@ -237,8 +243,7 @@ FGViewMgr::setPilotXOffset_m (double x) // FIXME: hard-coded pilot view position FGViewer * pilot_view = get_view(0); if (pilot_view != 0) { - float * offset = pilot_view->get_pilot_offset(); - pilot_view->set_pilot_offset(x, offset[1], offset[2]); + pilot_view->setXOffset_m(x); } } @@ -248,8 +253,7 @@ FGViewMgr::getPilotYOffset_m () const // FIXME: hard-coded pilot view position const FGViewer * pilot_view = get_view(0); if (pilot_view != 0) { - float * offset = ((FGViewer *)pilot_view)->get_pilot_offset(); - return offset[1]; + return ((FGViewer *)pilot_view)->getYOffset_m(); } else { return 0; } @@ -261,8 +265,7 @@ FGViewMgr::setPilotYOffset_m (double y) // FIXME: hard-coded pilot view position FGViewer * pilot_view = get_view(0); if (pilot_view != 0) { - float * offset = pilot_view->get_pilot_offset(); - pilot_view->set_pilot_offset(offset[0], y, offset[2]); + pilot_view->setYOffset_m(y); } } @@ -272,8 +275,7 @@ FGViewMgr::getPilotZOffset_m () const // FIXME: hard-coded pilot view position const FGViewer * pilot_view = get_view(0); if (pilot_view != 0) { - float * offset = ((FGViewer *)pilot_view)->get_pilot_offset(); - return offset[2]; + return ((FGViewer *)pilot_view)->getZOffset_m(); } else { return 0; } @@ -285,8 +287,7 @@ FGViewMgr::setPilotZOffset_m (double z) // FIXME: hard-coded pilot view position FGViewer * pilot_view = get_view(0); if (pilot_view != 0) { - float * offset = pilot_view->get_pilot_offset(); - pilot_view->set_pilot_offset(offset[0], offset[1], z); + pilot_view->setZOffset_m(z); } } @@ -358,5 +359,6 @@ FGViewMgr::do_axes () viewDir = SGD_RADIANS_TO_DEGREES * atan2 ( -axis_lat, -axis_long ); if ( viewDir < -1 ) viewDir += 360; - get_current_view()->set_goal_view_offset(viewDir*SGD_DEGREES_TO_RADIANS); + get_current_view()->set_goal_view_offset(viewDir); } + diff --git a/src/Main/viewmgr.hxx b/src/Main/viewmgr.hxx index 6e9b76298..fec031cf5 100644 --- a/src/Main/viewmgr.hxx +++ b/src/Main/viewmgr.hxx @@ -39,8 +39,7 @@ #include #include "fgfs.hxx" -#include "viewer_lookat.hxx" -#include "viewer_rph.hxx" +#include "viewer.hxx" SG_USING_STD(vector); @@ -107,8 +106,10 @@ public: // setters inline void clear() { views.clear(); } inline void set_view( const int v ) { current = v; } - inline void add_view( FGViewer * v ) { + inline void add_view( FGViewer * v, int type ) { views.push_back(v); + v->setType(type); + v->init(); } private: @@ -146,3 +147,7 @@ private: #endif // _VIEWMGR_HXX + + + + diff --git a/src/Scenery/newcache.cxx b/src/Scenery/newcache.cxx index d5d07a9b2..4968b08e0 100644 --- a/src/Scenery/newcache.cxx +++ b/src/Scenery/newcache.cxx @@ -133,7 +133,7 @@ bool FGNewCache::make_space() { if ( e->is_loaded() && (e->get_pending_models() == 0) ) { // calculate approximate distance from view point sgdCopyVec3( abs_view_pos, - globals->get_current_view()->get_abs_view_pos() ); + globals->get_current_view()->get_absolute_view_pos() ); SG_LOG( SG_TERRAIN, SG_DEBUG, "DIST Abs view pos = " << abs_view_pos[0] << "," @@ -220,3 +220,4 @@ bool FGNewCache::insert_tile( FGTileEntry *e ) { return false; } } + diff --git a/src/Scenery/tilemgr.cxx b/src/Scenery/tilemgr.cxx index a4f4285c2..1ef594afc 100644 --- a/src/Scenery/tilemgr.cxx +++ b/src/Scenery/tilemgr.cxx @@ -403,7 +403,7 @@ int FGTileMgr::update( double lon, double lat ) { scenery.get_center()[0], scenery.get_center()[1], scenery.get_center()[2] ); - hit = fgCurrentElev(globals->get_current_view()->get_abs_view_pos(), + hit = fgCurrentElev(globals->get_current_view()->get_absolute_view_pos(), sc, current_tile->get_terra_transform(), &hit_list, @@ -452,3 +452,4 @@ void FGTileMgr::prep_ssg_nodes() { tile_cache.next(); } } + diff --git a/src/Time/light.cxx b/src/Time/light.cxx index fa5617d37..0841cfbfb 100644 --- a/src/Time/light.cxx +++ b/src/Time/light.cxx @@ -175,17 +175,17 @@ void fgLIGHT::UpdateAdjFog( void ) { SG_LOG( SG_EVENT, SG_ALERT, "Psi rotation bad = " << f->get_Psi() ); exit(-1); } - if ( globals->get_current_view()->get_view_offset() < -2.0 * SGD_2PI || - globals->get_current_view()->get_view_offset() > 2.0 * SGD_2PI ) { + if ( globals->get_current_view()->getHeadingOffset_deg() * SGD_DEGREES_TO_RADIANS < -2.0 * SGD_2PI || + globals->get_current_view()->getHeadingOffset_deg() * SGD_DEGREES_TO_RADIANS > 2.0 * SGD_2PI ) { SG_LOG( SG_EVENT, SG_ALERT, "current view()->view offset bad = " - << globals->get_current_view()->get_view_offset() ); + << globals->get_current_view()->getHeadingOffset_deg() * SGD_DEGREES_TO_RADIANS ); exit(-1); } // first determine the difference between our view angle and local // direction to the sun rotation = -(sun_rotation + SGD_PI) - - (f->get_Psi() - globals->get_current_view()->get_view_offset()); + - (f->get_Psi() - globals->get_current_view()->getHeadingOffset_deg() * SGD_DEGREES_TO_RADIANS); if ( globals->get_current_view()->get_reverse_view_offset() ) { rotation += SGD_PI; } @@ -241,3 +241,4 @@ fgLIGHT::~fgLIGHT( void ) { } +