dst[1][3] = SG_ZERO ;
dst[0][3] = SG_ZERO ;
dst[3][3] = SG_ONE ;
-
}
// Constructor
SGLocation::SGLocation( void ):
- _dirty(true),
+ _position_dirty(true), _orientation_dirty(true),
_lon_deg(-1000),
_lat_deg(0),
_alt_ft(0),
_roll_deg(0),
_pitch_deg(0),
_heading_deg(0),
- _cur_elev_m(0),
- _tile_center(0)
+ _cur_elev_m(0)
{
sgdZeroVec3(_absolute_view_pos);
- sgZeroVec3(_relative_view_pos);
- sgZeroVec3(_zero_elev_view_pos);
sgMakeRotMat4( UP, 0.0, 0.0, 0.0 );
sgMakeRotMat4( TRANS, 0.0, 0.0, 0.0 );
}
SGLocation::~SGLocation( void ) {
}
-void
-SGLocation::init ()
-{
-}
-
-void
-SGLocation::bind ()
-{
-}
-
-void
-SGLocation::unbind ()
-{
-}
-
void
SGLocation::setPosition (double lon_deg, double lat_deg, double alt_ft)
{
- _dirty = true;
+ _position_dirty = true;
_lon_deg = lon_deg;
_lat_deg = lat_deg;
_alt_ft = alt_ft;
void
SGLocation::setOrientation (double roll_deg, double pitch_deg, double heading_deg)
{
- _dirty = true;
+ _orientation_dirty = true;
_roll_deg = roll_deg;
_pitch_deg = pitch_deg;
_heading_deg = heading_deg;
}
double *
-SGLocation::get_absolute_view_pos( const Point3D scenery_center )
+SGLocation::get_absolute_view_pos()
{
- if ( _dirty ) {
- recalc( scenery_center );
- }
+ recalcAbsolutePosition();
return _absolute_view_pos;
}
float *
-SGLocation::getRelativeViewPos( const Point3D scenery_center )
+SGLocation::get_view_pos( const Point3D& scenery_center )
{
- if ( _dirty ) {
- recalc( scenery_center );
- }
+ recalcAbsolutePosition();
+ for (int i = 0; i < 3; i++)
+ _relative_view_pos[i] = _absolute_view_pos[i] - scenery_center[i];
return _relative_view_pos;
}
-float *
-SGLocation::getZeroElevViewPos( const Point3D scenery_center )
-{
- if ( _dirty ) {
- recalc( scenery_center );
- }
- 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
-SGLocation::recalc( const Point3D scenery_center )
+SGLocation::recalcOrientation() const
{
+ if (_orientation_dirty) {
+ // Make sure UP matrix is up-to-date.
+ recalcAbsolutePosition();
- recalcPosition( _lon_deg, _lat_deg, _alt_ft, scenery_center );
-
- // 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,
+ // Create 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
-SGLocation::recalcPosition( double lon_deg, double lat_deg, double alt_ft,
- const Point3D scenery_center ) const
-{
- double lat = lat_deg * SGD_DEGREES_TO_RADIANS;
- double lon = lon_deg * SGD_DEGREES_TO_RADIANS;
- double alt = alt_ft * SG_FEET_TO_METER;
-
- sgGeodToCart(lat, lon, alt, _absolute_view_pos);
-
- int i;
- double ground[3];
- sgGeodToCart(lat, lon, 0, ground);
- for(i=0; i<3; i++)
- _zero_elev_view_pos[i] = ground[i] - _tile_center[i];
-
- // FIXME: view position should ONLY be calculated in the viewer...
- // Anything else should calculate their own positions relative to the
- // viewer's tile_center.
- for(i=0; i<3; i++)
- _relative_view_pos[i] = _absolute_view_pos[i] - scenery_center[i];
+ -_heading_deg * SG_DEGREES_TO_RADIANS,
+ UP );
+ _orientation_dirty = false;
+ }
}
+/*
+ * Update values derived from the longitude, latitude and altitude parameters
+ * of this instance. This encompasses absolute position in cartesian
+ * coordinates, the local up, east and south vectors and the UP Matrix.
+ */
void
-SGLocation::update (int dt)
+SGLocation::recalcAbsolutePosition() const
{
+ if (_position_dirty) {
+ double lat = _lat_deg * SGD_DEGREES_TO_RADIANS;
+ double lon = _lon_deg * SGD_DEGREES_TO_RADIANS;
+ double alt = _alt_ft * SG_FEET_TO_METER;
+
+ sgGeodToCart(lat, lon, alt, _absolute_view_pos);
+
+ // 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] );
+
+ // Calculate the surface east and south vectors using the (normalized)
+ // partial derivatives of the up vector Could also be fetched and
+ // normalized from the UP rotation matrix, but I doubt this would
+ // be more efficient.
+ float sin_lon = sin(_lon_deg * SGD_DEGREES_TO_RADIANS);
+ float sin_lat = sin(_lat_deg * SGD_DEGREES_TO_RADIANS);
+ float cos_lon = cos(_lon_deg * SGD_DEGREES_TO_RADIANS);
+ float cos_lat = cos(_lat_deg * SGD_DEGREES_TO_RADIANS);
+
+ _surface_south[0] = (sin_lat*cos_lon);
+ _surface_south[1] = (sin_lat*sin_lon);
+ _surface_south[2] = - cos_lat;
+
+ _surface_east[0] = -sin_lon;
+ _surface_east[1] = cos_lon;
+ _surface_east[2] = 0.f;
+
+ _position_dirty = false;
+ }
}
{
public:
-
// Constructor
SGLocation( void );
// Destructor
virtual ~SGLocation( void );
- //////////////////////////////////////////////////////////////////////
- // Part 1: standard FGSubsystem implementation.
- //////////////////////////////////////////////////////////////////////
-
- virtual void init ();
- virtual void bind ();
- virtual void unbind ();
- void update (int dt);
-
-
//////////////////////////////////////////////////////////////////////
// Part 2: user settings.
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
// 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( const Point3D scenery_center );
- // Get zero elev
- virtual float * get_zero_elev() { return _zero_elev_view_pos; }
+
+ //! Get the absolute view position in fgfs coordinates.
+ virtual double * get_absolute_view_pos( );
+
+ //! Return the position relative to the given scenery center.
+ virtual float * get_view_pos( const Point3D& scenery_center );
+
// 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( const Point3D scenery_center );
- // Get the absolute zero-elevation view position in fgfs coordinates.
- virtual float * getZeroElevViewPos( const Point3D scenery_center );
+ virtual float *get_world_up()
+ { recalcAbsolutePosition(); return _world_up; }
+
// Get surface east vector
- virtual float *get_surface_east() { return _surface_east; }
+ virtual float *get_surface_east()
+ { recalcAbsolutePosition(); return _surface_east; }
+
// Get surface south vector
- virtual float *get_surface_south() { return _surface_south; }
+ virtual float *get_surface_south()
+ { recalcAbsolutePosition(); return _surface_south; }
+
// Elevation of ground under location (based on scenery output)...
- void set_cur_elev_m ( double elev ) { _cur_elev_m = elev; }
- inline double get_cur_elev_m () { return _cur_elev_m; }
- // Interface to current buckets for use with tilemgr...
- void set_tile_center ( Point3D tile_center ) { set_dirty(); _tile_center = tile_center; }
- inline Point3D get_tile_center () { return _tile_center; }
-
+ void set_cur_elev_m ( double elev ) { _cur_elev_m = elev; }
+ inline double get_cur_elev_m () { return _cur_elev_m; }
+
// Matrices...
- virtual const sgVec4 *getTransformMatrix( const Point3D scenery_center ) {
- if ( _dirty || scenery_center != _scenery_center ) {
- _scenery_center = scenery_center;
- recalc( scenery_center );
- }
- return TRANS;
+ virtual const sgVec4 *getTransformMatrix() {
+ recalcOrientation();
+ return TRANS;
}
virtual const sgVec4 *getCachedTransformMatrix() { return TRANS; }
- virtual const sgVec4 *getUpMatrix( const Point3D scenery_center ) {
- if ( _dirty || scenery_center != _scenery_center ) {
- _scenery_center = scenery_center;
- recalc( scenery_center );
- }
- return UP;
+
+ virtual const sgVec4 *getUpMatrix(const Point3D& scenery_center) {
+ recalcAbsolutePosition();
+ return UP;
}
virtual const sgVec4 *getCachedUpMatrix() { return UP; }
-
private:
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// flag forcing a recalc of derived view parameters
- bool _dirty;
+ mutable bool _orientation_dirty, _position_dirty;
mutable sgdVec3 _absolute_view_pos;
mutable sgVec3 _relative_view_pos;
- mutable sgVec3 _zero_elev_view_pos;
double _lon_deg;
double _lat_deg;
// elevation of ground under this location...
double _cur_elev_m;
- Point3D _tile_center;
- Point3D _scenery_center;
// surface vector heading south
- sgVec3 _surface_south;
+ mutable sgVec3 _surface_south;
// surface vector heading east (used to unambiguously align sky
// with sun)
- sgVec3 _surface_east;
+ mutable 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;
+ // surface at the spot we are directly above)
+ mutable sgVec3 _world_up;
// sg versions of our friendly matrices
- sgMat4 TRANS, UP;
+ mutable sgMat4 TRANS, UP;
//////////////////////////////////////////////////////////////////
// private functions //
//////////////////////////////////////////////////////////////////
- void recalc( const Point3D scenery_center );
- void recalcPosition( double lon_deg, double lat_deg, double alt_ft,
- const Point3D scenery_center ) const;
-
- inline void set_dirty() { _dirty = true; }
- inline void set_clean() { _dirty = false; }
-
+ void recalcOrientation() const;
+ void recalcAbsolutePosition() const;
};
}
void
-SGModelPlacement::update( const Point3D scenery_center )
+SGModelPlacement::update()
{
_location->setPosition( _lon_deg, _lat_deg, _elev_ft );
_location->setOrientation( _roll_deg, _pitch_deg, _heading_deg );
- sgCopyMat4( POS, _location->getTransformMatrix(scenery_center) );
-
- sgVec3 trans;
- sgCopyVec3(trans, _location->get_view_pos());
-
- for(int i = 0; i < 4; i++) {
- float tmp = POS[i][3];
- for( int j=0; j<3; j++ ) {
- POS[i][j] += (tmp * trans[j]);
- }
- }
-// _position->setTransform(POS);
- _position->setTransform(_location->get_absolute_view_pos(scenery_center), POS);
- sgdVec3 center;
- sgdSetVec3(center,
- scenery_center.x(), scenery_center.y(), scenery_center.z());
- _position->setSceneryCenter(center);
+ sgMat4 rotation;
+ sgCopyMat4( rotation, _location->getTransformMatrix() );
+ _position->setTransform(_location->get_absolute_view_pos(), rotation);
}
bool
SGModelPlacement ();
virtual ~SGModelPlacement ();
- virtual void SGModelPlacement::init( ssgBranch * model );
- /* virtual void init( const string &fg_root,
- const string &path,
- SGPropertyNode *prop_root,
- double sim_time_sec, int dummy ); */
- virtual void update( const Point3D scenery_center );
+ virtual void SGModelPlacement::init( ssgBranch * model );
+
+ virtual void update();
virtual ssgEntity * getSceneGraph () { return (ssgEntity *)_selector; }
virtual void setOrientation (double roll_deg, double pitch_deg,
double heading_deg);
- // Addition by Diarmuid Tyson for Multiplayer Support
- // Allows multiplayer to get players position transform
- virtual const sgVec4 *get_POS() { return POS; }
-
ssgPlacementTransform * getTransform(void)
{ return _position; }
double _heading_deg;
ssgSelector * _selector;
-// ssgTransform * _position;
ssgPlacementTransform * _position;
// Location
SGLocation * _location;
-
-
- // Addition by Diarmuid Tyson for Multiplayer Support
- // Moved from update method
- // POS for transformation Matrix
- sgMat4 POS;
-
};
#endif // _SG_PLACEMENT_HXX