1
0
Fork 0

First baby steps towards restructuring the view architecture. I've

created a new class, FGViewPoint (declared in viewer.hxx) that holds a
single position in FlightGear coordinates, and have used it to factor
a lot of the common code out of viewer_lookat.cxx and viewer_rph.cxx.

I don't know whether this new class will stay or not; it might just be
a temporary step, or it might end up taking over much of the current
viewer functionality.  It would be a bad idea to code against it right
now.
This commit is contained in:
david 2002-03-06 16:03:33 +00:00
parent bdbd69effd
commit efe559ead4
4 changed files with 179 additions and 247 deletions

View file

@ -30,10 +30,110 @@
#include <simgear/debug/logstream.hxx> #include <simgear/debug/logstream.hxx>
#include <simgear/constants.h> #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 "viewer.hxx" #include "viewer.hxx"
////////////////////////////////////////////////////////////////////////
// Implementation of FGViewPoint.
////////////////////////////////////////////////////////////////////////
FGViewPoint::FGViewPoint ()
: _dirty(true),
_lon_deg(0),
_lat_deg(0),
_alt_ft(0)
{
}
FGViewPoint::~FGViewPoint ()
{
}
void
FGViewPoint::setPosition (double lon_deg, double lat_deg, double alt_ft)
{
_dirty = true;
_lon_deg = lon_deg;
_lat_deg = lat_deg;
_alt_ft = alt_ft;
}
const double *
FGViewPoint::getAbsoluteViewPos () const
{
if (_dirty)
recalc();
return _absolute_view_pos;
}
const float *
FGViewPoint::getRelativeViewPos () const
{
if (_dirty)
recalc();
return _relative_view_pos;
}
const float *
FGViewPoint::getZeroElevViewPos () const
{
if (_dirty)
recalc();
return _zero_elev_view_pos;
}
void
FGViewPoint::recalc () const
{
double sea_level_radius_m;
double lat_geoc_rad;
// Convert from geodetic to geocentric
// coordinates.
sgGeodToGeoc(_lat_deg * SGD_DEGREES_TO_RADIANS,
_alt_ft * SG_FEET_TO_METER,
&sea_level_radius_m,
&lat_geoc_rad);
// Calculate the cartesian coordinates
// of point directly below at sea level.
Point3D p = Point3D(_lon_deg * SG_DEGREES_TO_RADIANS,
lat_geoc_rad,
sea_level_radius_m);
Point3D tmp = sgPolarToCart3d(p) - scenery.get_center();
sgSetVec3(_zero_elev_view_pos, tmp[0], tmp[1], tmp[2]);
// Calculate the absolute view position
// in fgfs coordinates.
p.setz(p.radius() + _alt_ft * SG_FEET_TO_METER);
tmp = sgPolarToCart3d(p);
sgdSetVec3(_absolute_view_pos, tmp[0], tmp[1], tmp[2]);
// Calculate the relative view position
// from the scenery center.
sgdVec3 scenery_center;
sgdSetVec3(scenery_center,
scenery.get_center().x(),
scenery.get_center().y(),
scenery.get_center().z());
sgdVec3 view_pos;
sgdSubVec3(view_pos, _absolute_view_pos, scenery_center);
sgSetVec3(_relative_view_pos, view_pos);
}
////////////////////////////////////////////////////////////////////////
// Implementation of FGViewer.
////////////////////////////////////////////////////////////////////////
// Constructor // Constructor
FGViewer::FGViewer( void ): FGViewer::FGViewer( void ):
scalingType(FG_SCALING_MAX), scalingType(FG_SCALING_MAX),

View file

@ -42,6 +42,71 @@
#define FG_FOV_MAX 179.9 #define FG_FOV_MAX 179.9
/**
* Representation of a single viewpoint in the FlightGear world.
*/
class FGViewPoint
{
public:
FGViewPoint ();
virtual ~FGViewPoint ();
/**
* Set the geodetic position for the view point.
*/
virtual void setPosition (double lon_deg, double lat_deg, double alt_ft);
/**
* Get the longitude in degrees.
*/
virtual double getLongitude_deg () const { return _lon_deg; }
/**
* Get the latitude in degrees.
*/
virtual double getLatitude_deg () const { return _lat_deg; }
/**
* Get the altitude in feet ASL.
*/
virtual double getAltitudeASL_ft () const { return _alt_ft; }
/**
* Get the absolute view position in fgfs coordinates.
*/
virtual const double * getAbsoluteViewPos () const;
/**
* Get the relative view position in fgfs coordinates.
*
* The position is relative to the scenery centre.
*/
virtual const float * getRelativeViewPos () const;
/**
* Get the absolute zero-elevation view position in fgfs coordinates.
*/
virtual const float * getZeroElevViewPos () const;
private:
void recalc () const;
mutable sgdVec3 _absolute_view_pos;
mutable sgVec3 _relative_view_pos;
mutable sgVec3 _zero_elev_view_pos;
bool _dirty;
double _lon_deg;
double _lat_deg;
double _alt_ft;
};
// Define a structure containing view information // Define a structure containing view information
class FGViewer { class FGViewer {
@ -70,6 +135,8 @@ protected:
fgViewType _type; fgViewType _type;
fgScalingType scalingType; fgScalingType scalingType;
FGViewPoint view_point;
// the nominal field of view (angle, in degrees) // the nominal field of view (angle, in degrees)
double fov; double fov;

View file

@ -89,57 +89,16 @@ void fgMakeLookAtMat4 ( sgMat4 dst, const sgVec3 eye, const sgVec3 center,
} }
#if 0
// convert sgMat4 to MAT3 and print
static void print_sgMat4( sgMat4 &in) {
int i, j;
for ( i = 0; i < 4; i++ ) {
for ( j = 0; j < 4; j++ ) {
printf("%10.4f ", in[i][j]);
}
cout << endl;
}
}
#endif
// Update the view parameters // Update the view parameters
void FGViewerLookAt::update() { void FGViewerLookAt::update() {
Point3D tmp;
sgVec3 minus_z; sgVec3 minus_z;
// convert to geocentric coordinates view_point.setPosition(geod_view_pos[0] * SGD_RADIANS_TO_DEGREES,
double geoc_lat; geod_view_pos[1] * SGD_RADIANS_TO_DEGREES,
sgGeodToGeoc( geod_view_pos[1], geod_view_pos[2], geod_view_pos[2] * SG_METER_TO_FEET);
&sea_level_radius, &geoc_lat ); sgCopyVec3(zero_elev, view_point.getZeroElevViewPos());
sgdCopyVec3(abs_view_pos, view_point.getAbsoluteViewPos());
// calculate the cartesion coords of the current lat/lon/0 elev sgCopyVec3(view_pos, view_point.getRelativeViewPos());
Point3D p = Point3D( geod_view_pos[0], geoc_lat, sea_level_radius );
tmp = sgPolarToCart3d(p) - scenery.get_center();
sgSetVec3( zero_elev, tmp[0], tmp[1], tmp[2] );
// calculate view position in current FG view coordinate system
// p.lon & p.lat are already defined earlier, p.radius was set to
// the sea level radius, so now we add in our altitude.
if ( geod_view_pos[2] > (scenery.get_cur_elev() + 0.5 * SG_METER_TO_FEET) ) {
p.setz( p.radius() + geod_view_pos[2] );
} else {
p.setz( p.radius() + scenery.get_cur_elev() + 0.5 * SG_METER_TO_FEET );
}
tmp = sgPolarToCart3d(p);
sgdSetVec3( abs_view_pos, tmp[0], tmp[1], tmp[2] );
// view_pos = abs_view_pos - scenery.center;
sgdVec3 sc;
sgdSetVec3( sc,
scenery.get_center().x(),
scenery.get_center().y(),
scenery.get_center().z() );
sgdVec3 vp;
sgdSubVec3( vp, abs_view_pos, sc );
sgSetVec3( view_pos, vp );
sgVec3 tmp_offset; sgVec3 tmp_offset;
sgCopyVec3( tmp_offset, pilot_offset ); sgCopyVec3( tmp_offset, pilot_offset );
@ -159,30 +118,8 @@ void FGViewerLookAt::update() {
sgAddVec3( view_pos, tmp_offset ); sgAddVec3( view_pos, tmp_offset );
// !!!!!!!!!! testing // !!!!!!!!!! testing
// sgAddVec3( view_pos, pilot_offset );
SG_LOG( SG_VIEW, SG_DEBUG, "sea level radius = " << sea_level_radius );
SG_LOG( SG_VIEW, SG_DEBUG, "Polar view pos = " << p );
SG_LOG( SG_VIEW, SG_DEBUG, "Absolute view pos = "
<< abs_view_pos[0] << ","
<< abs_view_pos[1] << ","
<< abs_view_pos[2] );
SG_LOG( SG_VIEW, SG_DEBUG, "Relative view pos = "
<< view_pos[0] << "," << view_pos[1] << "," << view_pos[2] );
SG_LOG( SG_VIEW, SG_DEBUG, "pilot offset = "
<< pilot_offset[0] << "," << pilot_offset[1] << ","
<< pilot_offset[2] );
SG_LOG( SG_VIEW, SG_DEBUG, "view forward = "
<< view_forward[0] << "," << view_forward[1] << ","
<< view_forward[2] );
SG_LOG( SG_VIEW, SG_DEBUG, "view up = "
<< view_up[0] << "," << view_up[1] << ","
<< view_up[2] );
// Make the VIEW matrix. // Make the VIEW matrix.
fgMakeLookAtMat4( VIEW, view_pos, view_forward, view_up ); fgMakeLookAtMat4( VIEW, view_pos, view_forward, view_up );
// cout << "VIEW matrix" << endl;
// print_sgMat4( VIEW );
// the VIEW matrix includes both rotation and translation. Let's // the VIEW matrix includes both rotation and translation. Let's
// knock out the translation part to make the VIEW_ROT matrix // knock out the translation part to make the VIEW_ROT matrix
@ -198,9 +135,6 @@ void FGViewerLookAt::update() {
// use a clever observation into the nature of our tranformation // use a clever observation into the nature of our tranformation
// matrix to grab the world_up vector // matrix to grab the world_up vector
sgSetVec3( world_up, UP[0][0], UP[0][1], UP[0][2] ); sgSetVec3( world_up, UP[0][0], UP[0][1], UP[0][2] );
// cout << "World Up = " << world_up[0] << "," << world_up[1] << ","
// << world_up[2] << endl;
// Given a vector pointing straight down (-Z), map into onto the // Given a vector pointing straight down (-Z), map into onto the
// local plane representing "horizontal". This should give us the // local plane representing "horizontal". This should give us the
@ -210,25 +144,11 @@ void FGViewerLookAt::update() {
sgmap_vec_onto_cur_surface_plane(world_up, view_pos, minus_z, sgmap_vec_onto_cur_surface_plane(world_up, view_pos, minus_z,
surface_south); surface_south);
sgNormalizeVec3(surface_south); sgNormalizeVec3(surface_south);
// cout << "Surface direction directly south " << surface_south[0] << ","
// << surface_south[1] << "," << surface_south[2] << endl;
// now calculate the surface east vector // now calculate the surface east vector
#define USE_FAST_SURFACE_EAST
#ifdef USE_FAST_SURFACE_EAST
sgVec3 world_down; sgVec3 world_down;
sgNegateVec3(world_down, world_up); sgNegateVec3(world_down, world_up);
sgVectorProductVec3(surface_east, surface_south, world_down); sgVectorProductVec3(surface_east, surface_south, world_down);
#else
sgMakeRotMat4( TMP, SGD_PI_2 * SGD_RADIANS_TO_DEGREES, world_up );
// cout << "sgMat4 TMP" << endl;
// print_sgMat4( TMP );
sgXformVec3(surface_east, surface_south, TMP);
#endif // USE_FAST_SURFACE_EAST
// cout << "Surface direction directly east " << surface_east[0] << ","
// << surface_east[1] << "," << surface_east[2] << endl;
// cout << "Should be close to zero = "
// << sgScalarProductVec3(surface_south, surface_east) << endl;
set_clean(); set_clean();
} }

View file

@ -48,33 +48,9 @@
FGViewerRPH::FGViewerRPH( void ) FGViewerRPH::FGViewerRPH( void )
{ {
set_reverse_view_offset(false); set_reverse_view_offset(false);
#ifndef USE_FAST_VIEWROT
// This never changes -- NHV
LARC_TO_SSG[0][0] = 0.0;
LARC_TO_SSG[0][1] = 1.0;
LARC_TO_SSG[0][2] = -0.0;
LARC_TO_SSG[0][3] = 0.0;
LARC_TO_SSG[1][0] = 0.0;
LARC_TO_SSG[1][1] = 0.0;
LARC_TO_SSG[1][2] = 1.0;
LARC_TO_SSG[1][3] = 0.0;
LARC_TO_SSG[2][0] = 1.0;
LARC_TO_SSG[2][1] = -0.0;
LARC_TO_SSG[2][2] = 0.0;
LARC_TO_SSG[2][3] = 0.0;
LARC_TO_SSG[3][0] = 0.0;
LARC_TO_SSG[3][1] = 0.0;
LARC_TO_SSG[3][2] = 0.0;
LARC_TO_SSG[3][3] = 1.0;
#endif // USE_FAST_VIEWROT
} }
#define USE_FAST_VIEWROT
#ifdef USE_FAST_VIEWROT
// VIEW_ROT = LARC_TO_SSG * ( VIEWo * VIEW_OFFSET ) // VIEW_ROT = LARC_TO_SSG * ( VIEWo * VIEW_OFFSET )
// This takes advantage of the fact that VIEWo and VIEW_OFFSET // This takes advantage of the fact that VIEWo and VIEW_OFFSET
// only have entries in the upper 3x3 block // only have entries in the upper 3x3 block
@ -102,11 +78,8 @@ inline static void fgMakeViewRot( sgMat4 dst, const sgMat4 m1, const sgMat4 m2 )
dst[3][2] = SG_ZERO; dst[3][2] = SG_ZERO;
dst[3][3] = SG_ONE; dst[3][3] = SG_ONE;
} }
#endif
#define USE_FAST_LOCAL
#ifdef USE_FAST_LOCAL
inline static void fgMakeLOCAL( sgMat4 dst, const double Theta, inline static void fgMakeLOCAL( sgMat4 dst, const double Theta,
const double Phi, const double Psi) const double Phi, const double Psi)
{ {
@ -137,145 +110,39 @@ inline static void fgMakeLOCAL( sgMat4 dst, const double Theta,
dst[3][2] = SG_ZERO; dst[3][2] = SG_ZERO;
dst[3][3] = SG_ONE ; dst[3][3] = SG_ONE ;
} }
#endif
#if 0
// convert sgMat4 to MAT3 and print
static void print_sgMat4( sgMat4 &in) {
int i, j;
for ( i = 0; i < 4; i++ ) {
for ( j = 0; j < 4; j++ ) {
printf("%10.4f ", in[i][j]);
}
cout << endl;
}
}
#endif
// Update the view parameters // Update the view parameters
void FGViewerRPH::update() { void FGViewerRPH::update() {
Point3D tmp;
sgVec3 minus_z, right, forward, tilt; sgVec3 minus_z, right, forward, tilt;
sgMat4 VIEWo; sgMat4 VIEWo;
// convert to geocentric coordinates view_point.setPosition(geod_view_pos[0] * SGD_RADIANS_TO_DEGREES,
double geoc_lat; geod_view_pos[1] * SGD_RADIANS_TO_DEGREES,
sgGeodToGeoc( geod_view_pos[1], geod_view_pos[2], geod_view_pos[2] * SG_METER_TO_FEET);
&sea_level_radius, &geoc_lat ); sgCopyVec3(zero_elev, view_point.getZeroElevViewPos());
sgdCopyVec3(abs_view_pos, view_point.getAbsoluteViewPos());
// calculate the cartesion coords of the current lat/lon/0 elev sgCopyVec3(view_pos, view_point.getRelativeViewPos());
Point3D p = Point3D( geod_view_pos[0], geoc_lat, sea_level_radius );
tmp = sgPolarToCart3d(p) - scenery.get_center();
sgSetVec3( zero_elev, tmp[0], tmp[1], tmp[2] );
// calculate view position in current FG view coordinate system
// p.lon & p.lat are already defined earlier, p.radius was set to
// the sea level radius, so now we add in our altitude.
if ( geod_view_pos[2] > (scenery.get_cur_elev() + 0.5 * SG_METER_TO_FEET) ) {
p.setz( p.radius() + geod_view_pos[2] );
} else {
p.setz( p.radius() + scenery.get_cur_elev() + 0.5 * SG_METER_TO_FEET );
}
tmp = sgPolarToCart3d(p);
sgdSetVec3( abs_view_pos, tmp[0], tmp[1], tmp[2] );
// view_pos = abs_view_pos - scenery.center;
sgdVec3 sc;
sgdSetVec3( sc,
scenery.get_center().x(),
scenery.get_center().y(),
scenery.get_center().z() );
sgdVec3 vp;
sgdSubVec3( vp, abs_view_pos, sc );
sgSetVec3( view_pos, vp );
SG_LOG( SG_VIEW, SG_DEBUG, "sea level radius = " << sea_level_radius );
SG_LOG( SG_VIEW, SG_DEBUG, "Polar view pos = " << p );
SG_LOG( SG_VIEW, SG_DEBUG, "Absolute view pos = "
<< abs_view_pos[0] << ","
<< abs_view_pos[1] << ","
<< abs_view_pos[2] );
SG_LOG( SG_VIEW, SG_DEBUG, "Scenery center = "
<< sc[0] << "," << sc[1] << "," << sc[2] );
SG_LOG( SG_VIEW, SG_DEBUG, "(RPH) Relative view pos = "
<< view_pos[0] << "," << view_pos[1] << "," << view_pos[2] );
// code to calculate LOCAL matrix calculated from Phi, Theta, and // code to calculate LOCAL matrix calculated from Phi, Theta, and
// Psi (roll, pitch, yaw) in case we aren't running LaRCsim as our // Psi (roll, pitch, yaw) in case we aren't running LaRCsim as our
// flight model // flight model
#ifdef USE_FAST_LOCAL
fgMakeLOCAL( LOCAL, rph[1], rph[0], -rph[2] ); fgMakeLOCAL( LOCAL, rph[1], rph[0], -rph[2] );
#else // USE_TEXT_BOOK_METHOD
sgVec3 rollvec;
sgSetVec3( rollvec, 0.0, 0.0, 1.0 );
sgMat4 PHI; // roll
sgMakeRotMat4( PHI, rph[0] * SGD_RADIANS_TO_DEGREES, rollvec );
sgVec3 pitchvec;
sgSetVec3( pitchvec, 0.0, 1.0, 0.0 );
sgMat4 THETA; // pitch
sgMakeRotMat4( THETA, rph[1] * SGD_RADIANS_TO_DEGREES, pitchvec );
// ROT = PHI * THETA
sgMat4 ROT;
// sgMultMat4( ROT, PHI, THETA );
sgCopyMat4( ROT, PHI );
sgPostMultMat4( ROT, THETA );
sgVec3 yawvec;
sgSetVec3( yawvec, 1.0, 0.0, 0.0 );
sgMat4 PSI; // heading
sgMakeRotMat4( PSI, -rph[2] * SGD_RADIANS_TO_DEGREES, yawvec );
// LOCAL = ROT * PSI
// sgMultMat4( LOCAL, ROT, PSI );
sgCopyMat4( LOCAL, ROT );
sgPostMultMat4( LOCAL, PSI );
#endif // USE_FAST_LOCAL
// cout << "LOCAL matrix" << endl;
// print_sgMat4( LOCAL );
sgMakeRotMat4( UP, sgMakeRotMat4( UP,
geod_view_pos[0] * SGD_RADIANS_TO_DEGREES, geod_view_pos[0] * SGD_RADIANS_TO_DEGREES,
0.0, 0.0,
-geod_view_pos[1] * SGD_RADIANS_TO_DEGREES ); -geod_view_pos[1] * SGD_RADIANS_TO_DEGREES );
sgSetVec3( world_up, UP[0][0], UP[0][1], UP[0][2] ); sgSetVec3( world_up, UP[0][0], UP[0][1], UP[0][2] );
// sgXformVec3( world_up, UP );
// cout << "World Up = " << world_up[0] << "," << world_up[1] << ","
// << world_up[2] << endl;
// Alternative method to Derive world up vector based on
// *geodetic* coordinates
// alt_up = sgPolarToCart(FG_Longitude, FG_Latitude, 1.0);
// printf( " Alt Up = (%.4f, %.4f, %.4f)\n",
// alt_up.x, alt_up.y, alt_up.z);
// VIEWo = LOCAL * UP
// sgMultMat4( VIEWo, LOCAL, UP );
sgCopyMat4( VIEWo, LOCAL ); sgCopyMat4( VIEWo, LOCAL );
sgPostMultMat4( VIEWo, UP ); sgPostMultMat4( VIEWo, UP );
// cout << "VIEWo matrix" << endl;
// print_sgMat4( VIEWo );
// generate the sg view up and forward vectors // generate the sg view up and forward vectors
sgSetVec3( view_up, VIEWo[0][0], VIEWo[0][1], VIEWo[0][2] ); sgSetVec3( view_up, VIEWo[0][0], VIEWo[0][1], VIEWo[0][2] );
// cout << "view = " << view[0] << ","
// << view[1] << "," << view[2] << endl;
sgSetVec3( right, VIEWo[1][0], VIEWo[1][1], VIEWo[1][2] ); sgSetVec3( right, VIEWo[1][0], VIEWo[1][1], VIEWo[1][2] );
sgSetVec3( forward, VIEWo[2][0], VIEWo[2][1], VIEWo[2][2] ); sgSetVec3( forward, VIEWo[2][0], VIEWo[2][1], VIEWo[2][2] );
// cout << "forward = " << forward[0] << ","
// << forward[1] << "," << forward[2] << endl;
// generate the pilot offset vector in world coordinates // generate the pilot offset vector in world coordinates
sgVec3 pilot_offset_world; sgVec3 pilot_offset_world;
@ -297,17 +164,7 @@ void FGViewerRPH::update() {
<< view_forward[2] ); << view_forward[2] );
// VIEW_ROT = LARC_TO_SSG * ( VIEWo * VIEW_OFFSET ) // VIEW_ROT = LARC_TO_SSG * ( VIEWo * VIEW_OFFSET )
#ifdef USE_FAST_VIEWROT
fgMakeViewRot( VIEW_ROT, VIEW_OFFSET, VIEWo ); fgMakeViewRot( VIEW_ROT, VIEW_OFFSET, VIEWo );
#else
// sgMultMat4( VIEW_ROT, VIEW_OFFSET, VIEWo );
// sgPreMultMat4( VIEW_ROT, LARC_TO_SSG );
sgCopyMat4( VIEW_ROT, VIEWo );
sgPostMultMat4( VIEW_ROT, VIEW_OFFSET );
sgPreMultMat4( VIEW_ROT, LARC_TO_SSG );
#endif
// cout << "VIEW_ROT matrix" << endl;
// print_sgMat4( VIEW_ROT );
sgVec3 trans_vec; sgVec3 trans_vec;
sgAddVec3( trans_vec, view_pos, pilot_offset_world ); sgAddVec3( trans_vec, view_pos, pilot_offset_world );
@ -336,21 +193,9 @@ void FGViewerRPH::update() {
// << surface_south[1] << "," << surface_south[2] << endl; // << surface_south[1] << "," << surface_south[2] << endl;
// now calculate the surface east vector // now calculate the surface east vector
#define USE_FAST_SURFACE_EAST
#ifdef USE_FAST_SURFACE_EAST
sgVec3 world_down; sgVec3 world_down;
sgNegateVec3(world_down, world_up); sgNegateVec3(world_down, world_up);
sgVectorProductVec3(surface_east, surface_south, world_down); sgVectorProductVec3(surface_east, surface_south, world_down);
#else
sgMakeRotMat4( TMP, SGD_PI_2 * SGD_RADIANS_TO_DEGREES, world_up );
// cout << "sgMat4 TMP" << endl;
// print_sgMat4( TMP );
sgXformVec3(surface_east, surface_south, TMP);
#endif // USE_FAST_SURFACE_EAST
// cout << "Surface direction directly east " << surface_east[0] << ","
// << surface_east[1] << "," << surface_east[2] << endl;
// cout << "Should be close to zero = "
// << sgScalarProductVec3(surface_south, surface_east) << endl;
set_clean(); set_clean();
} }