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 \
INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src
endif
+
} 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") {
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.
////////////////////////////////////////////////////////////////////
}
}
+
--- /dev/null
+// 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 <simgear/compiler.h>
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <simgear/debug/logstream.hxx>
+#include <simgear/constants.h>
+#include <simgear/math/point3d.hxx>
+#include <simgear/math/polar3d.hxx>
+#include <simgear/math/sg_geodesy.hxx>
+
+#include <Scenery/scenery.hxx>
+
+#include <simgear/math/vector.hxx>
+/*
+#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)
+{
+}
+
+
+
--- /dev/null
+// 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 <simgear/compiler.h>
+#include <simgear/constants.h>
+
+#include <plib/sg.h> // 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
+
+
+
+
+
+
+
+
+
+
+
+
+
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 );
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()
ssgSetNearFar( scene_nearplane, scene_farplane );
ssgCullAndDraw( scene );
- globals->get_aircraft_model()->update(dt_ms);
-
// change state for lighting here
// draw lighting
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 );
// << " 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() ) {
// do nothing
}
+
+ globals->get_aircraft_model()->update(multi_loop);
+
// update the view angle
globals->get_viewmgr()->update(multi_loop);
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" );
+
+
#include <simgear/math/sg_geodesy.hxx>
#include <Scenery/scenery.hxx>
+//#include <Main/location.hxx>
-/* from lookat */
#include <simgear/math/vector.hxx>
-#include "globals.hxx"
-/* end from lookat */
+#include <Main/globals.hxx>
+#include <Model/acmodel.hxx>
#include "viewer.hxx"
////////////////////////////////////////////////////////////////////////
// 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),
_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
}
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
FGViewer::setType ( int type )
{
if (type == 0)
- _type = FG_RPH;
+ _type = FG_LOOKFROM;
if (type == 1)
_type = FG_LOOKAT;
}
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
{
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);
// 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();
}
+
+
#include "fgfs.hxx"
+#include <Main/location.hxx>
#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)
};
// Constructor
- FGViewer( void );
+ FGViewer( fgViewType Type, bool from_model, int from_model_index, bool at_model, int at_model_index );
// Destructor
virtual ~FGViewer( void );
// 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; }
//////////////////////////////////////////////////////////////////////
}
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:
//////////////////////////////////////////////////////////////////
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;
// 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
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 ) {
#endif // _VIEWER_HXX
-
-
-
-
-
-
-
-
-
-
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 ));
}
}
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()));
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();
}
}
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();
// 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();
}
#endif // _VIEWMGR_HXX
-
-
-
-