From 42a5ee93d79c5adb76c3a3a94d056fdbcaf7e913 Mon Sep 17 00:00:00 2001 From: curt Date: Thu, 11 Apr 2002 04:26:07 +0000 Subject: [PATCH] This patch includes the FGLocation class, a few fixes, cleanup in viewer code. Synced to CVS 19:36 EDT 2002-04-10 (after this evenings JSMsim and Base package updates). Description: Added FGLocation class which is new home for calculating matrix rotations. Viewer can now be configured to access rotations created by the model rather than repeating the same calculations again. Changed model initialization for the time being so that its location data is available for the viewer (currently required by other subsystems). At some point we can move this back to fg_init along with the viewer initialization. Seperated the update from the draw function in the model code. The viewer code needs the same matrix data, and moving the update portion at this time does not increase the number of matrix math iterations. Moved the model draw so that it always appears "in front" of lights and clouds. Reogranized viewer update routine for using the FGLocation class and simplified some more tasks. The routine is fairly easy to follow now, with the steps ordered and spelled out in comments. Viewmgr only updates the current (visible) view now, with the exception of an old reference to "chase view" that will be corrected in forthcoming changes. Also will be doing some work on the viewmgr outputs. Model is now clears the z-buffer in all modes. This will be changed with the next viewmgr update. The only side effect is that models always disappear when over 5km distant from the eye point (can't really see them anyway:-)). Other than a flag to indicate "internal" view I don't anticipate the configuration interface for viewmgr/views will be changed a lot for now. It is close to done. The next viewmgr update will however rework the outputs so may change location. This code will run with the previous version of preferences.xml, but will run faster with the newer version. I am attaching a preferences.xml that should not be commited before the code. All the changes are in the /sim/view section and should show a simpler view configuration that references model locations. Note that I've added a 2nd tower view in "lookfrom" mode for illustration purposes. You can look around using the mouse. You may want to remove that or comment it out. --- src/Main/Makefile.am | 4 +- src/Main/fg_init.cxx | 12 +- src/Main/location.cxx | 262 ++++++++++++++++++++++++++++++++++++++++++ src/Main/location.hxx | 163 ++++++++++++++++++++++++++ src/Main/main.cxx | 28 ++++- src/Main/viewer.cxx | 262 ++++++++++++++++++++++++------------------ src/Main/viewer.hxx | 55 ++++----- src/Main/viewmgr.cxx | 96 ++++++++++++---- src/Main/viewmgr.hxx | 7 +- 9 files changed, 704 insertions(+), 185 deletions(-) create mode 100644 src/Main/location.cxx create mode 100644 src/Main/location.hxx diff --git a/src/Main/Makefile.am b/src/Main/Makefile.am index 1e216706f..27ba8c0a4 100644 --- a/src/Main/Makefile.am +++ b/src/Main/Makefile.am @@ -51,7 +51,8 @@ fgfs_SOURCES = \ options.cxx options.hxx \ splash.cxx splash.hxx \ viewer.cxx viewer.hxx \ - viewmgr.cxx viewmgr.hxx + viewmgr.cxx viewmgr.hxx \ + location.cxx location.hxx fgfs_LDADD = \ $(top_builddir)/src/Aircraft/libAircraft.a \ @@ -95,3 +96,4 @@ else INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src endif + diff --git a/src/Main/fg_init.cxx b/src/Main/fg_init.cxx index dd67485a7..be061a1d2 100644 --- a/src/Main/fg_init.cxx +++ b/src/Main/fg_init.cxx @@ -590,7 +590,7 @@ void fgInitFDM() { } else if (model == "external") { cur_fdm_state = new FGExternal( dt ); } else if (model == "network") { - cur_fdm_state = new FGExternalNet( dt, 5501, 5502, 5503, "localhost" ); + cur_fdm_state = new FGExternalNet( dt, 5501, 5502, 5503, "10.0.2.4" ); } else if (model == "null") { cur_fdm_state = new FGNullFDM( dt ); } else if (model == "yasim") { @@ -1030,15 +1030,6 @@ bool fgInitSubsystems( void ) { current_input.bind(); - //////////////////////////////////////////////////////////////////// - // Initialize the 3D aircraft model subsystem. - //////////////////////////////////////////////////////////////////// - - globals->set_aircraft_model(new FGAircraftModel); - globals->get_aircraft_model()->init(); - globals->get_aircraft_model()->bind(); - - //////////////////////////////////////////////////////////////////////// // End of subsystem initialization. //////////////////////////////////////////////////////////////////// @@ -1107,3 +1098,4 @@ void fgReInitSubsystems( void ) } } + diff --git a/src/Main/location.cxx b/src/Main/location.cxx new file mode 100644 index 000000000..f77e4e179 --- /dev/null +++ b/src/Main/location.cxx @@ -0,0 +1,262 @@ +// location.hxx -- class for determining model location in the flightgear world. +// +// Written by Jim Wilson, David Megginson, started April 2002. +// overhaul started October 2000. +// +// This file is in the Public Domain, and comes with no warranty. + + + +#include + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#include + +#include + +#include +/* +#include "globals.hxx" +*/ + +#include "location.hxx" + + +/** + * make model transformation Matrix - based on optimizations by NHV + */ +static void MakeTRANS( sgMat4 dst, const double Theta, + const double Phi, const double Psi, + const sgMat4 UP) +{ + 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) ; + + sgMat4 tmp; + + tmp[0][0] = cosPhi * cosTheta; + tmp[0][1] = sinPhi * cosPsi + cosPhi * -sinTheta * -sinPsi; + tmp[0][2] = sinPhi * sinPsi + cosPhi * -sinTheta * cosPsi; + + tmp[1][0] = -sinPhi * cosTheta; + tmp[1][1] = cosPhi * cosPsi + -sinPhi * -sinTheta * -sinPsi; + tmp[1][2] = cosPhi * sinPsi + -sinPhi * -sinTheta * cosPsi; + + tmp[2][0] = sinTheta; + tmp[2][1] = cosTheta * -sinPsi; + tmp[2][2] = cosTheta * cosPsi; + + float a = UP[0][0]; + float b = UP[1][0]; + float c = UP[2][0]; + dst[2][0] = a*tmp[0][0] + b*tmp[0][1] + c*tmp[0][2] ; + dst[1][0] = a*tmp[1][0] + b*tmp[1][1] + c*tmp[1][2] ; + dst[0][0] = -(a*tmp[2][0] + b*tmp[2][1] + c*tmp[2][2]) ; + dst[3][0] = SG_ZERO ; + + a = UP[0][1]; + b = UP[1][1]; + c = UP[2][1]; + dst[2][1] = a*tmp[0][0] + b*tmp[0][1] + c*tmp[0][2] ; + dst[1][1] = a*tmp[1][0] + b*tmp[1][1] + c*tmp[1][2] ; + dst[0][1] = -(a*tmp[2][0] + b*tmp[2][1] + c*tmp[2][2]) ; + dst[3][1] = SG_ZERO ; + + a = UP[0][2]; + c = UP[2][2]; + dst[2][2] = a*tmp[0][0] + c*tmp[0][2] ; + dst[1][2] = a*tmp[1][0] + c*tmp[1][2] ; + dst[0][2] = -(a*tmp[2][0] + c*tmp[2][2]) ; + dst[3][2] = SG_ZERO ; + + dst[2][3] = SG_ZERO ; + dst[1][3] = SG_ZERO ; + dst[0][3] = SG_ZERO ; + dst[3][3] = SG_ONE ; + +} + + +//////////////////////////////////////////////////////////////////////// +// Implementation of FGLocation. +//////////////////////////////////////////////////////////////////////// + +// Constructor +FGLocation::FGLocation( void ): + _dirty(true), + _lon_deg(0), + _lat_deg(0), + _alt_ft(0), + _roll_deg(0), + _pitch_deg(0), + _heading_deg(0) +{ + sgdZeroVec3(_absolute_view_pos); +} + + +// Destructor +FGLocation::~FGLocation( void ) { +} + +void +FGLocation::init () +{ +} + +void +FGLocation::bind () +{ +} + +void +FGLocation::unbind () +{ +} + +void +FGLocation::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 +FGLocation::setOrientation (double roll_deg, double pitch_deg, double heading_deg) +{ + _dirty = true; + _roll_deg = roll_deg; + _pitch_deg = pitch_deg; + _heading_deg = heading_deg; +} + +double * +FGLocation::get_absolute_view_pos () +{ + if (_dirty) + recalc(); + return _absolute_view_pos; +} + +float * +FGLocation::getRelativeViewPos () +{ + if (_dirty) + recalc(); + return _relative_view_pos; +} + +float * +FGLocation::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") on the next "get". It calculates all the outputs +// for viewer. +void +FGLocation::recalc () +{ + + recalcPosition( _lon_deg, _lat_deg, _alt_ft ); + + // Make the world up rotation matrix for eye positioin... + sgMakeRotMat4( UP, _lon_deg, 0.0, -_lat_deg ); + + + // get the world up radial vector from planet center for output + sgSetVec3( _world_up, UP[0][0], UP[0][1], UP[0][2] ); + + // Creat local matrix with current geodetic position. Converting + // the orientation (pitch/roll/heading) to vectors. + MakeTRANS( TRANS, _pitch_deg * SG_DEGREES_TO_RADIANS, + _roll_deg * SG_DEGREES_TO_RADIANS, + -_heading_deg * SG_DEGREES_TO_RADIANS, + UP); + + // 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". + sgVec3 minus_z; + sgSetVec3( minus_z, 0.0, 0.0, -1.0 ); + + sgmap_vec_onto_cur_surface_plane(_world_up, _relative_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 +FGLocation::recalcPosition (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); + +} + +void +FGLocation::update (int dt) +{ +} + + + diff --git a/src/Main/location.hxx b/src/Main/location.hxx new file mode 100644 index 000000000..e0ac78396 --- /dev/null +++ b/src/Main/location.hxx @@ -0,0 +1,163 @@ +// location.hxx -- class for determining model location in the flightgear world. +// +// Written by Jim Wilson, David Megginson, started April 2002. +// overhaul started October 2000. +// +// This file is in the Public Domain, and comes with no warranty. + + +#ifndef _LOCATION_HXX +#define _LOCATION_HXX + + +#ifndef __cplusplus +# error This library requires C++ +#endif + +#include +#include + +#include // plib include + +#include "fgfs.hxx" + + +// Define a structure containing view information +class FGLocation +{ + +public: + + // Constructor + FGLocation( void ); + + // Destructor + virtual ~FGLocation( void ); + + ////////////////////////////////////////////////////////////////////// + // Part 1: standard FGSubsystem implementation. + ////////////////////////////////////////////////////////////////////// + + virtual void init (); + virtual void bind (); + virtual void unbind (); + void update (int dt); + + + ////////////////////////////////////////////////////////////////////// + // Part 2: user settings. + ////////////////////////////////////////////////////////////////////// + + // Geodetic position of model... + virtual double getLongitude_deg () const { return _lon_deg; } + virtual double getLatitude_deg () const { return _lat_deg; } + virtual double getAltitudeASL_ft () const { return _alt_ft; } + virtual void setPosition (double lon_deg, double lat_deg, double alt_ft); + + + // Reference orientation rotations... + // These are rotations that represent the plane attitude effect on + // the view (in Pilot view). IE The view frustrum rotates as the plane + // turns, pitches, and rolls. + // In model view (lookat/chaseview) these end up changing the angle that + // the eye is looking at the ojbect (ie the model). + // FIXME: the FGModel class should have its own version of these so that + // it can generate it's own model rotations. + 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 setOrientation (double roll_deg, double pitch_deg, double heading_deg); + + + ////////////////////////////////////////////////////////////////////// + // Part 3: output vectors and matrices in FlightGear coordinates. + ////////////////////////////////////////////////////////////////////// + + // Vectors and positions... + + // Get zero view_pos + virtual float * get_view_pos() { return _relative_view_pos; } + // Get the absolute view position in fgfs coordinates. + virtual double * get_absolute_view_pos (); + // Get zero elev + virtual float * get_zero_elev() { return _zero_elev_view_pos; } + // Get world up vector + virtual float *get_world_up() { 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() { return _surface_east; } + // Get surface south vector + virtual float *get_surface_south() { return _surface_south; } + + // Matrices... + virtual const sgMat4 &getTransformMatrix() { if ( _dirty ) { recalc(); } return TRANS; } + virtual const sgMat4 &getCachedTransformMatrix() { return TRANS; } + virtual const sgMat4 &getUpMatrix() { if ( _dirty ) { recalc(); } return UP; } + virtual const sgMat4 &getCachedUpMatrix() { return UP; } + + +private: + + ////////////////////////////////////////////////////////////////// + // private data // + ////////////////////////////////////////////////////////////////// + + // flag forcing a recalc of derived view parameters + bool _dirty; + + 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 _roll_deg; + double _pitch_deg; + double _heading_deg; + + // surface vector heading south + sgVec3 _surface_south; + + // surface vector heading east (used to unambiguously align sky + // with sun) + sgVec3 _surface_east; + + // world up vector (normal to the plane tangent to the earth's + // surface at the spot we are directly above + sgVec3 _world_up; + + // sg versions of our friendly matrices + sgMat4 TRANS, UP; + + ////////////////////////////////////////////////////////////////// + // private functions // + ////////////////////////////////////////////////////////////////// + + void recalc (); + void recalcPosition (double lon_deg, double lat_deg, double alt_ft) const; + + inline void set_dirty() { _dirty = true; } + inline void set_clean() { _dirty = false; } + +}; + + +#endif // _LOCATION_HXX + + + + + + + + + + + + + diff --git a/src/Main/main.cxx b/src/Main/main.cxx index 4afd1125d..7c099785a 100644 --- a/src/Main/main.cxx +++ b/src/Main/main.cxx @@ -376,8 +376,6 @@ void trRenderFrame( void ) { ssgSetNearFar( scene_nearplane, scene_farplane ); ssgCullAndDraw( scene ); - globals->get_aircraft_model()->update(0); - // draw the lights glFogf (GL_FOG_DENSITY, fog_exp2_punch_through); ssgSetNearFar( scene_nearplane, scene_farplane ); @@ -385,6 +383,8 @@ void trRenderFrame( void ) { thesky->postDraw( cur_fdm_state->get_Altitude() * SG_FEET_TO_METER ); + globals->get_aircraft_model()->draw(); + // need to do this here as hud_and_panel state is static to // main.cxx and HUD and Panel routines have to be called with // knowledge of the the TR struct < see gui.cxx::HighResDump() @@ -655,8 +655,6 @@ void fgRenderFrame( void ) { ssgSetNearFar( scene_nearplane, scene_farplane ); ssgCullAndDraw( scene ); - globals->get_aircraft_model()->update(dt_ms); - // change state for lighting here // draw lighting @@ -721,6 +719,8 @@ void fgRenderFrame( void ) { thesky->postDraw( cur_fdm_state->get_Altitude() * SG_FEET_TO_METER ); } + globals->get_aircraft_model()->draw(); + // display HUD && Panel glDisable( GL_FOG ); glDisable( GL_DEPTH_TEST ); @@ -780,7 +780,7 @@ void fgUpdateTimeDepCalcs() { // << " cur_elev = " << scenery.get_cur_elev() << endl; if ( !cur_fdm_state->get_inited() && scenery.get_cur_elev() > -9990 ) { - SG_LOG(SG_FLIGHT,SG_INFO, "Finally initializing fdm"); + SG_LOG(SG_FLIGHT,SG_INFO, "Finally initializing fdm"); cur_fdm_state->init(); if ( cur_fdm_state->get_bound() ) { @@ -845,6 +845,9 @@ void fgUpdateTimeDepCalcs() { // do nothing } + + globals->get_aircraft_model()->update(multi_loop); + // update the view angle globals->get_viewmgr()->update(multi_loop); @@ -1476,11 +1479,24 @@ int mainLoop( int argc, char **argv ) { SGPath modelpath( globals->get_fg_root() ); ssgModelPath( (char *)modelpath.c_str() ); + //////////////////////////////////////////////////////////////////// + // Initialize the 3D aircraft model subsystem. + //////////////////////////////////////////////////////////////////// + + globals->set_aircraft_model(new FGAircraftModel); + globals->get_aircraft_model()->init(); + globals->get_aircraft_model()->bind(); + + //////////////////////////////////////////////////////////////////// + // Initialize the view manager subsystem. + //////////////////////////////////////////////////////////////////// + FGViewMgr *viewmgr = new FGViewMgr; globals->set_viewmgr( viewmgr ); viewmgr->init(); viewmgr->bind(); + // Scene graph root scene = new ssgRoot; scene->setName( "Scene" ); @@ -1945,3 +1961,5 @@ void fgUpdateDCS (void) { + + diff --git a/src/Main/viewer.cxx b/src/Main/viewer.cxx index 8ff56cb35..64a6d906f 100644 --- a/src/Main/viewer.cxx +++ b/src/Main/viewer.cxx @@ -39,11 +39,11 @@ #include #include +//#include
-/* from lookat */ #include -#include "globals.hxx" -/* end from lookat */ +#include
+#include #include "viewer.hxx" @@ -197,7 +197,7 @@ inline static void MakeWithWorldUp( sgMat4 dst, const sgMat4 UP, const sgMat4 LO //////////////////////////////////////////////////////////////////////// // Constructor -FGViewer::FGViewer( void ): +FGViewer::FGViewer( fgViewType Type, bool from_model, int from_model_index, bool at_model, int at_model_index ): _scaling_type(FG_SCALING_MAX), _fov_deg(55.0), _dirty(true), @@ -220,6 +220,11 @@ FGViewer::FGViewer( void ): _goal_pitch_offset_deg(0.0) { sgdZeroVec3(_absolute_view_pos); + _type = Type; + _from_model = from_model; + _from_model_index = from_model_index; + _at_model = at_model; + _at_model_index = at_model_index; //a reasonable guess for init, so that the math doesn't blow up } @@ -231,6 +236,17 @@ FGViewer::~FGViewer( void ) { void FGViewer::init () { + if ( _from_model ) + _location = (FGLocation *) globals->get_aircraft_model()->get3DModel()->getFGLocation(); + else + _location = (FGLocation *) new FGLocation; + + if ( _type == FG_LOOKAT ) { + if ( _at_model ) + _target_location = (FGLocation *) globals->get_aircraft_model()->get3DModel()->getFGLocation(); + else + _target_location = (FGLocation *) new FGLocation; + } } void @@ -247,7 +263,7 @@ void FGViewer::setType ( int type ) { if (type == 0) - _type = FG_RPH; + _type = FG_LOOKFROM; if (type == 1) _type = FG_LOOKAT; } @@ -490,6 +506,41 @@ FGViewer::getZeroElevViewPos () return _zero_elev_view_pos; } +void +FGViewer::updateFromModelLocation (FGLocation * location) +{ + sgCopyMat4(LOCAL, location->getCachedTransformMatrix()); + _lon_deg = location->getLongitude_deg(); + _lat_deg = location->getLatitude_deg(); + _alt_ft = location->getAltitudeASL_ft(); + _roll_deg = location->getRoll_deg(); + _pitch_deg = location->getPitch_deg(); + _heading_deg = location->getHeading_deg(); + sgCopyVec3(_zero_elev_view_pos, location->get_zero_elev()); + sgCopyVec3(_relative_view_pos, location->get_view_pos()); + sgdCopyVec3(_absolute_view_pos, location->get_absolute_view_pos()); + sgCopyMat4(UP, location->getCachedUpMatrix()); + sgCopyVec3(_world_up, location->get_world_up()); + // these are the vectors that the sun and moon code like to get... + sgCopyVec3(_surface_east, location->get_surface_east()); + sgCopyVec3(_surface_south, location->get_surface_south()); +} + +void +FGViewer::recalcOurOwnLocation (double lon_deg, double lat_deg, double alt_ft, + double roll_deg, double pitch_deg, double heading_deg) +{ + // update from our own data... + _location->setPosition( lon_deg, lat_deg, alt_ft ); + _location->setOrientation( roll_deg, pitch_deg, heading_deg ); + sgCopyMat4(LOCAL, _location->getTransformMatrix()); + sgCopyVec3(_zero_elev_view_pos, _location->get_zero_elev()); + sgCopyVec3(_relative_view_pos, _location->get_view_pos()); + sgdCopyVec3(_absolute_view_pos, _location->get_absolute_view_pos()); + // these are the vectors that the sun and moon code like to get... + sgCopyVec3(_surface_east, _location->get_surface_east()); + sgCopyVec3(_surface_south, _location->get_surface_south()); +} // recalc() is done every time one of the setters is called (making the // cached data "dirty") on the next "get". It calculates all the outputs @@ -499,26 +550,57 @@ FGViewer::recalc () { sgVec3 minus_z, right, forward, tilt; sgMat4 tmpROT; // temp rotation work matrices - sgMat4 VIEW_HEADINGOFFSET, VIEW_PITCHOFFSET; - sgVec3 tmpVec3; // temp work vector (3) - sgVec3 eye_pos, object_pos; + sgVec3 eye_pos, at_pos; // The position vectors originate from the view point or target location // depending on the type of view. - // FIXME: Later note: actually the object (target) info needs to be held - // by the model class. - if (_type == FG_RPH) { - // eye position is the location of the pilot - recalcPositionVectors( _lon_deg, _lat_deg, _alt_ft ); + if (_type == FG_LOOKFROM) { + // LOOKFROM mode... + if ( _from_model ) { + // update or data from model location + updateFromModelLocation(_location); + } else { + // update from our own data... + recalcOurOwnLocation( _lon_deg, _lat_deg, _alt_ft, + _roll_deg, _pitch_deg, _heading_deg ); + // get world up data from just recalced location + sgCopyMat4(UP, _location->getUpMatrix()); + sgCopyVec3(_world_up, _location->get_world_up()); + } + } else { - // eye position is now calculated based on lon/lat; - recalcPositionVectors( _lon_deg, _lat_deg, _alt_ft ); - sgCopyVec3(eye_pos, _relative_view_pos); - // object position is the location of the object being looked at - recalcPositionVectors( _target_lon_deg, _target_lat_deg, _target_alt_ft ); + // LOOKAT mode... + if ( _from_model ) { + // update or data from model location + updateFromModelLocation(_location); + } else { + // update from our own data, just the rotation here... + recalcOurOwnLocation( _lon_deg, _lat_deg, _alt_ft, + _roll_deg, _pitch_deg, _heading_deg ); + // get world up data from just recalced location + sgCopyMat4(UP, _location->getUpMatrix()); + sgCopyVec3(_world_up, _location->get_world_up()); + } + // save they eye positon... + sgCopyVec3(eye_pos, _location->get_view_pos()); + // save the eye rotation before getting target values!!! + sgCopyMat4(tmpROT, LOCAL); + + if ( _at_model ) { + // update or data from model location + updateFromModelLocation(_target_location); + } else { + // if not model then calculate our own target position... + recalcOurOwnLocation( _target_lon_deg, _target_lat_deg, _target_alt_ft, + _target_roll_deg, _target_pitch_deg, _target_heading_deg ); + } + // restore the eye rotation (the from position rotation) + sgCopyMat4(LOCAL, tmpROT); + } + // the coordinates generated by the above "recalcPositionVectors" sgCopyVec3(_zero_elev, _zero_elev_view_pos); sgCopyVec3(_view_pos, _relative_view_pos); @@ -527,139 +609,87 @@ FGViewer::recalc () // Doing this last recalc here for published values...where the airplane is // This should be per aircraft or model (for published values) before // multiple FDM can be done. - recalcPositionVectors(fgGetDouble("/position/longitude-deg"), + // This info should come directly from the model (not through viewer), + // because in some cases there is no model directly assigned as a lookfrom + // position. The problem that arises is related to the FDM interface looking + // indirectly to the viewer to find the altitude of the aircraft on the runway. + // + // Note that recalcPositionVectors can be removed from viewer when this + // issue is addressed. + // + if (!_from_model) { + recalcPositionVectors(fgGetDouble("/position/longitude-deg"), fgGetDouble("/position/latitude-deg"), fgGetDouble("/position/altitude-ft")); - - - - // Make the world up rotation matrix for eye positioin... - sgMakeRotMat4( UP, _lon_deg, 0.0, -_lat_deg ); - - - // get the world up radial vector from planet center - // (ie. effect of aircraft location on earth "sphere" approximation) - sgSetVec3( _world_up, UP[0][0], UP[0][1], UP[0][2] ); - - - - // Creat local matrix with current geodetic position. Converting - // the orientation (pitch/roll/heading) to vectors. - fgMakeLOCAL( LOCAL, _pitch_deg * SG_DEGREES_TO_RADIANS, - _roll_deg * SG_DEGREES_TO_RADIANS, - -_heading_deg * SG_DEGREES_TO_RADIANS); - // Adjust LOCAL to current world_up vector (adjustment for planet location) - MakeWithWorldUp( LOCAL, UP, LOCAL ); - // copy the LOCAL matrix to COCKPIT_ROT for publication... - sgCopyMat4( LOCAL_ROT, LOCAL ); + } // make sg vectors view up, right and forward vectors from LOCAL - sgSetVec3( _view_up, LOCAL[0][0], LOCAL[0][1], LOCAL[0][2] ); + sgSetVec3( _view_up, LOCAL[2][0], LOCAL[2][1], LOCAL[2][2] ); sgSetVec3( right, LOCAL[1][0], LOCAL[1][1], LOCAL[1][2] ); - sgSetVec3( forward, LOCAL[2][0], LOCAL[2][1], LOCAL[2][2] ); + sgSetVec3( forward, -LOCAL[0][0], -LOCAL[0][1], -LOCAL[0][2] ); - - - // create xyz offsets Vector + // create the (xyz) eye Position offsets Vector sgVec3 position_offset; - sgSetVec3( position_offset, _y_offset_m, _x_offset_m, _z_offset_m ); + sgSetVec3( position_offset, -_z_offset_m, _x_offset_m, _y_offset_m ); - // Eye rotations. - // Looking up/down left/right in pilot view (lookfrom mode) - // or Floating Rotatation around the object in chase view (lookat mode). - // Generate the offset matrix to be applied using offset angles: if (_type == FG_LOOKAT) { + // Note that when in "lookat" view the "world up" vector is always applied // to the viewer. World up is based on verticle at a given lon/lat (see // matrix "UP" above). + + // Orientation Offsets matrix MakeVIEW_OFFSET( VIEW_OFFSET, - _heading_offset_deg * SG_DEGREES_TO_RADIANS, _world_up, + (_heading_offset_deg -_heading_deg) * SG_DEGREES_TO_RADIANS, _world_up, _pitch_offset_deg * SG_DEGREES_TO_RADIANS, right ); - } - if (_type == FG_RPH) { - // Note that when in "lookfrom" view the "view up" vector is always applied - // to the viewer. View up is based on verticle of the aircraft itself. (see - // "LOCAL" matrix above) - MakeVIEW_OFFSET( VIEW_OFFSET, - _heading_offset_deg * SG_DEGREES_TO_RADIANS, _view_up, - _pitch_offset_deg * SG_DEGREES_TO_RADIANS, right ); - } - - - - if (_type == FG_LOOKAT) { - // transfrom "offset" and "orientation offset" to vector + // Eye Position Offsets to vector sgXformVec3( position_offset, position_offset, UP ); - // add heading to offset so that the eye does heading as such... - sgMakeRotMat4(tmpROT, -_heading_deg, _world_up); - sgPostMultMat4(VIEW_OFFSET, tmpROT); + // add in the Orientation Offsets here sgXformVec3( position_offset, position_offset, VIEW_OFFSET ); - // add the offsets from object to the eye position + // add the Position offsets from object to the eye position sgAddVec3( eye_pos, eye_pos, position_offset ); - // copy object - sgCopyVec3( object_pos, _view_pos ); - // Make the VIEW matrix for "lookat". - sgMakeLookAtMat4( VIEW, eye_pos, object_pos, _view_up ); + // at position (what we are looking at) + sgCopyVec3( at_pos, _view_pos ); + + // Make the VIEW matrix for a "LOOKAT". + sgMakeLookAtMat4( VIEW, eye_pos, at_pos, _view_up ); } - if (_type == FG_RPH) { + if (_type == FG_LOOKFROM) { + // Note that when in "lookfrom" view the "view up" vector is always applied + // to the viewer. View up is based on verticle of the aircraft itself. (see + // "LOCAL" matrix above) + + // Orientation Offsets matrix + MakeVIEW_OFFSET( VIEW_OFFSET, + _heading_offset_deg * SG_DEGREES_TO_RADIANS, _view_up, + _pitch_offset_deg * SG_DEGREES_TO_RADIANS, right ); + + // Eye Position Offsets to vector sgXformVec3( position_offset, position_offset, LOCAL); - // add the offsets including rotations to the coordinates + + // add the offsets including rotations to the translation vector sgAddVec3( _view_pos, position_offset ); // Make the VIEW matrix. - VIEW[0][0] = right[0]; - VIEW[0][1] = right[1]; - VIEW[0][2] = right[2]; - VIEW[0][3] = 0.0; - VIEW[1][0] = forward[0]; - VIEW[1][1] = forward[1]; - VIEW[1][2] = forward[2]; - VIEW[1][3] = 0.0; - VIEW[2][0] = _view_up[0]; - VIEW[2][1] = _view_up[1]; - VIEW[2][2] = _view_up[2]; - VIEW[2][3] = 0.0; - VIEW[3][0] = 0.0; - VIEW[3][1] = 0.0; - VIEW[3][2] = 0.0; - VIEW[3][3] = 0.0; + sgSetVec4(VIEW[0], right[0], right[1], right[2],SG_ZERO); + sgSetVec4(VIEW[1], forward[0], forward[1], forward[2],SG_ZERO); + sgSetVec4(VIEW[2], _view_up[0], _view_up[1], _view_up[2],SG_ZERO); + sgSetVec4(VIEW[3], SG_ZERO, SG_ZERO, SG_ZERO,SG_ONE); // multiply the OFFSETS (for heading and pitch) into the VIEW sgPostMultMat4(VIEW, VIEW_OFFSET); // add the position data to the matrix - VIEW[3][0] = _view_pos[0]; - VIEW[3][1] = _view_pos[1]; - VIEW[3][2] = _view_pos[2]; - VIEW[3][3] = 1.0f; + sgSetVec4(VIEW[3], _view_pos[0], _view_pos[1], _view_pos[2],SG_ONE); } - // 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; - - // 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(); } @@ -807,3 +837,5 @@ FGViewer::update (int dt) + + diff --git a/src/Main/viewer.hxx b/src/Main/viewer.hxx index feda79145..ce3216450 100644 --- a/src/Main/viewer.hxx +++ b/src/Main/viewer.hxx @@ -39,22 +39,21 @@ #include "fgfs.hxx" +#include
#define FG_FOV_MIN 0.1 #define FG_FOV_MAX 179.9 +enum fgViewType { + FG_LOOKFROM = 0, + FG_LOOKAT = 1, +}; // Define a structure containing view information class FGViewer : public FGSubsystem { public: - enum fgViewType { - FG_RPH = 0, - FG_LOOKAT = 1, - FG_HPR = 2 - }; - enum fgScalingType { // nominal Field Of View actually applies to ... FG_SCALING_WIDTH, // window width FG_SCALING_MAX, // max(width, height) @@ -63,7 +62,7 @@ public: }; // Constructor - FGViewer( void ); + FGViewer( fgViewType Type, bool from_model, int from_model_index, bool at_model, int at_model_index ); // Destructor virtual ~FGViewer( void ); @@ -214,8 +213,6 @@ public: // 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_LOCAL_ROT() { if ( _dirty ) { recalc(); } return LOCAL_ROT; } virtual const sgVec4 *get_UP() { if ( _dirty ) { recalc(); } return UP; } ////////////////////////////////////////////////////////////////////// @@ -234,6 +231,14 @@ public: } virtual double get_aspect_ratio() const { return _aspect_ratio; } + ////////////////////////////////////////////////////////////////////// + // Part 5: misc setters and getters + ////////////////////////////////////////////////////////////////////// + + inline void set_dirty() { _dirty = true; } + inline void set_clean() { _dirty = false; } + + private: ////////////////////////////////////////////////////////////////// @@ -279,6 +284,17 @@ private: fgViewType _type; fgScalingType _scaling_type; + // view is looking from a model + bool _from_model; + int _from_model_index; // number of model (for multi model) + + // view is looking at a model + bool _at_model; + int _at_model_index; // number of model (for multi model) + + FGLocation * _location; + FGLocation * _target_location; + // the nominal field of view (angle, in degrees) double _fov_deg; @@ -310,11 +326,8 @@ private: // top of the aircraft sgVec3 _view_up; -// // the vector pointing straight out the nose of the aircraft -// sgVec3 _view_forward; - // sg versions of our friendly matrices - sgMat4 VIEW, VIEW_ROT, UP, LOCAL_ROT; + sgMat4 VIEW, UP; sgMat4 LOCAL, TRANS, LARC_TO_SSG; // Transformation matrix for the view direction offset relative to @@ -327,9 +340,9 @@ private: void recalc (); void recalcPositionVectors (double lon_deg, double lat_deg, double alt_ft) const; - - inline void set_dirty() { _dirty = true; } - inline void set_clean() { _dirty = false; } + void updateFromModelLocation (FGLocation * location); + void recalcOurOwnLocation (double lon_deg, double lat_deg, double alt_ft, + double roll_deg, double pitch_deg, double heading_deg); // add to _heading_offset_deg inline void incHeadingOffset_deg( double amt ) { @@ -351,13 +364,3 @@ private: #endif // _VIEWER_HXX - - - - - - - - - - diff --git a/src/Main/viewmgr.cxx b/src/Main/viewmgr.cxx index 2d8b3f7eb..971480647 100644 --- a/src/Main/viewmgr.cxx +++ b/src/Main/viewmgr.cxx @@ -50,17 +50,55 @@ void FGViewMgr::init () { char stridx [ 20 ]; + bool from_model = false; + bool at_model = false; + int from_model_index = 0; + int at_model_index = 0; + for (int i = 0; i < fgGetInt("/sim/number-views"); i++) { - nodepath = "/sim/view"; + viewpath = "/sim/view"; sprintf(stridx, "[%d]", i); - nodepath += stridx; + viewpath += stridx; + + // find out what type of view this is... + nodepath = viewpath; nodepath += "/type"; strdata = fgGetString(nodepath.c_str()); - // supporting two types now "lookat" = 1 and "lookfrom" = 1 + + // FIXME: + // this is assumed to be an aircraft model...we will need to read + // model-from-type as well. + // find out if this is a model we are looking from... + nodepath = viewpath; + nodepath += "/config/from-model"; + from_model = fgGetBool(nodepath.c_str()); + + // get model index (which model) + if (from_model) { + nodepath = viewpath; + nodepath += "/config/from-model-idx"; + from_model_index = fgGetInt(nodepath.c_str()); + } + + if ( strcmp("lookat",strdata.c_str()) == 0 ) { + // find out if this is a model we are looking at... + nodepath = viewpath; + nodepath += "/config/at-model"; + at_model = fgGetBool(nodepath.c_str()); + + // get model index (which model) + if (at_model) { + nodepath = viewpath; + nodepath += "/config/at-model-idx"; + at_model_index = fgGetInt(nodepath.c_str()); + } + } + + // supporting two types now "lookat" = 1 and "lookfrom" = 0 if ( strcmp("lookat",strdata.c_str()) == 0 ) - add_view(new FGViewer, 1); + add_view(new FGViewer ( FG_LOOKAT, from_model, from_model_index, at_model, at_model_index )); else - add_view(new FGViewer, 0); + add_view(new FGViewer ( FG_LOOKFROM, from_model, from_model_index, false, 0 )); } } @@ -122,44 +160,56 @@ void FGViewMgr::update (int dt) { char stridx [20]; + double lon_deg, lat_deg, alt_ft, roll_deg, pitch_deg, heading_deg; FGViewer * view = get_current_view(); if (view == 0) return; - for (int i = 0; i < fgGetInt("/sim/number-views"); i++) { - viewpath = "/sim/view"; - sprintf(stridx, "[%d]", i); - viewpath += stridx; + // + int i = current; + viewpath = "/sim/view"; + sprintf(stridx, "[%d]", i); + viewpath += stridx; + + FGViewer *loop_view = (FGViewer *)get_view( i ); - FGViewer *loop_view = (FGViewer *)get_view( i ); + // Set up view location and orientation - // Set up view + nodepath = viewpath; + nodepath += "/config/from-model"; + if (!fgGetBool(nodepath.c_str())) { nodepath = viewpath; nodepath += "/config/eye-lon-deg-path"; - double lon_deg = fgGetDouble(fgGetString(nodepath.c_str())); + lon_deg = fgGetDouble(fgGetString(nodepath.c_str())); nodepath = viewpath; nodepath += "/config/eye-lat-deg-path"; - double lat_deg = fgGetDouble(fgGetString(nodepath.c_str())); + lat_deg = fgGetDouble(fgGetString(nodepath.c_str())); nodepath = viewpath; nodepath += "/config/eye-alt-ft-path"; - double alt_ft = fgGetDouble(fgGetString(nodepath.c_str())); + alt_ft = fgGetDouble(fgGetString(nodepath.c_str())); nodepath = viewpath; nodepath += "/config/eye-roll-deg-path"; - double roll_deg = fgGetDouble(fgGetString(nodepath.c_str())); + roll_deg = fgGetDouble(fgGetString(nodepath.c_str())); nodepath = viewpath; nodepath += "/config/eye-pitch-deg-path"; - double pitch_deg = fgGetDouble(fgGetString(nodepath.c_str())); + pitch_deg = fgGetDouble(fgGetString(nodepath.c_str())); nodepath = viewpath; nodepath += "/config/eye-heading-deg-path"; - double heading_deg = fgGetDouble(fgGetString(nodepath.c_str())); - + heading_deg = fgGetDouble(fgGetString(nodepath.c_str())); loop_view->setPosition(lon_deg, lat_deg, alt_ft); loop_view->setOrientation(roll_deg, pitch_deg, heading_deg); + } else { + // force recalc in viewer + loop_view->set_dirty(); + } - // if lookat (type 1) then get target data... - if (loop_view->getType() == 1) { + // if lookat (type 1) then get target data... + if (loop_view->getType() == 1) { + nodepath = viewpath; + nodepath += "/config/from-model"; + if (!fgGetBool(nodepath.c_str())) { nodepath = viewpath; nodepath += "/config/target-lon-deg-path"; lon_deg = fgGetDouble(fgGetString(nodepath.c_str())); @@ -178,9 +228,11 @@ FGViewMgr::update (int dt) nodepath = viewpath; nodepath += "/config/target-heading-deg-path"; heading_deg = fgGetDouble(fgGetString(nodepath.c_str())); - + loop_view ->setTargetPosition(lon_deg, lat_deg, alt_ft); loop_view->setTargetOrientation(roll_deg, pitch_deg, heading_deg); + } else { + loop_view->set_dirty(); } } @@ -197,7 +249,7 @@ FGViewMgr::update (int dt) sgVec3 *pPO = PilotOffsetGet(); sgVec3 zPO; sgCopyVec3( zPO, *pPO ); - chase_view->setPositionOffsets(zPO[1], zPO[0], zPO[2] ); + chase_view->setPositionOffsets(zPO[1], zPO[2], zPO[0] ); // Update the current view do_axes(); diff --git a/src/Main/viewmgr.hxx b/src/Main/viewmgr.hxx index fec031cf5..e1dcff32b 100644 --- a/src/Main/viewmgr.hxx +++ b/src/Main/viewmgr.hxx @@ -106,9 +106,8 @@ public: // setters inline void clear() { views.clear(); } inline void set_view( const int v ) { current = v; } - inline void add_view( FGViewer * v, int type ) { + inline void add_view( FGViewer * v ) { views.push_back(v); - v->setType(type); v->init(); } @@ -147,7 +146,3 @@ private: #endif // _VIEWMGR_HXX - - - - -- 2.39.5