Mathias Frhlich:

There was a patch from Manuel Masing a few months ago which cleaned up
SGLocation's way depending on input values. That means that with that patch
SGLocation does no longer have calls with unneeded input arguments.
I took his patch and integrated that into flightgear and made maximum use of
that changes.
This commit is contained in:
ehofman
2005-09-05 13:23:55 +00:00
parent 669d9a89ca
commit 00ab198c9f
4 changed files with 97 additions and 193 deletions

View File

@@ -93,7 +93,6 @@ static void MakeTRANS( sgMat4 dst, const double Theta,
dst[1][3] = SG_ZERO ;
dst[0][3] = SG_ZERO ;
dst[3][3] = SG_ONE ;
}
@@ -103,19 +102,16 @@ static void MakeTRANS( sgMat4 dst, const double Theta,
// 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 );
}
@@ -125,25 +121,10 @@ SGLocation::SGLocation( void ):
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;
@@ -152,105 +133,83 @@ SGLocation::setPosition (double lon_deg, double lat_deg, double 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();
-_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::recalcPosition( double lon_deg, double lat_deg, double alt_ft,
const Point3D scenery_center ) const
SGLocation::recalcAbsolutePosition() 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;
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);
sgGeodToCart(lat, lon, alt, _absolute_view_pos);
// Make the world up rotation matrix for eye positioin...
sgMakeRotMat4( UP, _lon_deg, 0.0, -_lat_deg );
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];
// get the world up radial vector from planet center for output
sgSetVec3( _world_up, UP[0][0], UP[0][1], UP[0][2] );
// 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];
}
void
SGLocation::update (int dt)
{
// 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;
}
}

View File

@@ -41,23 +41,12 @@ class SGLocation
{
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.
//////////////////////////////////////////////////////////////////////
@@ -88,49 +77,42 @@ public:
//////////////////////////////////////////////////////////////////////
// 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:
//////////////////////////////////////////////////////////////////
@@ -138,11 +120,10 @@ 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;
@@ -154,34 +135,27 @@ private:
// 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;
};

View File

@@ -54,28 +54,14 @@ SGModelPlacement::init( ssgBranch * model )
}
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

View File

@@ -46,12 +46,9 @@ public:
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; }
@@ -79,10 +76,6 @@ public:
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; }
@@ -99,18 +92,10 @@ private:
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