1 // location.hxx -- class for determining model location in the flightgear world.
3 // Written by Jim Wilson, David Megginson, started April 2002.
4 // overhaul started October 2000.
6 // This file is in the Public Domain, and comes with no warranty.
10 #include <simgear/compiler.h>
16 #include <simgear/debug/logstream.hxx>
17 #include <simgear/constants.h>
18 #include <simgear/math/point3d.hxx>
19 #include <simgear/math/polar3d.hxx>
20 #include <simgear/math/sg_geodesy.hxx>
22 #include <Scenery/scenery.hxx>
24 #include <simgear/math/vector.hxx>
26 #include "globals.hxx"
29 #include "location.hxx"
33 * make model transformation Matrix - based on optimizations by NHV
35 static void MakeTRANS( sgMat4 dst, const double Theta,
36 const double Phi, const double Psi,
39 SGfloat cosTheta = (SGfloat) cos(Theta);
40 SGfloat sinTheta = (SGfloat) sin(Theta);
41 SGfloat cosPhi = (SGfloat) cos(Phi);
42 SGfloat sinPhi = (SGfloat) sin(Phi);
43 SGfloat sinPsi = (SGfloat) sin(Psi) ;
44 SGfloat cosPsi = (SGfloat) cos(Psi) ;
48 tmp[0][0] = cosPhi * cosTheta;
49 tmp[0][1] = sinPhi * cosPsi + cosPhi * -sinTheta * -sinPsi;
50 tmp[0][2] = sinPhi * sinPsi + cosPhi * -sinTheta * cosPsi;
52 tmp[1][0] = -sinPhi * cosTheta;
53 tmp[1][1] = cosPhi * cosPsi + -sinPhi * -sinTheta * -sinPsi;
54 tmp[1][2] = cosPhi * sinPsi + -sinPhi * -sinTheta * cosPsi;
57 tmp[2][1] = cosTheta * -sinPsi;
58 tmp[2][2] = cosTheta * cosPsi;
63 dst[2][0] = a*tmp[0][0] + b*tmp[0][1] + c*tmp[0][2] ;
64 dst[1][0] = a*tmp[1][0] + b*tmp[1][1] + c*tmp[1][2] ;
65 dst[0][0] = -(a*tmp[2][0] + b*tmp[2][1] + c*tmp[2][2]) ;
71 dst[2][1] = a*tmp[0][0] + b*tmp[0][1] + c*tmp[0][2] ;
72 dst[1][1] = a*tmp[1][0] + b*tmp[1][1] + c*tmp[1][2] ;
73 dst[0][1] = -(a*tmp[2][0] + b*tmp[2][1] + c*tmp[2][2]) ;
78 dst[2][2] = a*tmp[0][0] + c*tmp[0][2] ;
79 dst[1][2] = a*tmp[1][0] + c*tmp[1][2] ;
80 dst[0][2] = -(a*tmp[2][0] + c*tmp[2][2]) ;
91 ////////////////////////////////////////////////////////////////////////
92 // Implementation of FGLocation.
93 ////////////////////////////////////////////////////////////////////////
96 FGLocation::FGLocation( void ):
105 sgdZeroVec3(_absolute_view_pos);
110 FGLocation::~FGLocation( void ) {
124 FGLocation::unbind ()
129 FGLocation::setPosition (double lon_deg, double lat_deg, double alt_ft)
138 FGLocation::setOrientation (double roll_deg, double pitch_deg, double heading_deg)
141 _roll_deg = roll_deg;
142 _pitch_deg = pitch_deg;
143 _heading_deg = heading_deg;
147 FGLocation::get_absolute_view_pos ()
151 return _absolute_view_pos;
155 FGLocation::getRelativeViewPos ()
159 return _relative_view_pos;
163 FGLocation::getZeroElevViewPos ()
167 return _zero_elev_view_pos;
171 // recalc() is done every time one of the setters is called (making the
172 // cached data "dirty") on the next "get". It calculates all the outputs
175 FGLocation::recalc ()
178 recalcPosition( _lon_deg, _lat_deg, _alt_ft );
180 // Make the world up rotation matrix for eye positioin...
181 sgMakeRotMat4( UP, _lon_deg, 0.0, -_lat_deg );
184 // get the world up radial vector from planet center for output
185 sgSetVec3( _world_up, UP[0][0], UP[0][1], UP[0][2] );
187 // Creat local matrix with current geodetic position. Converting
188 // the orientation (pitch/roll/heading) to vectors.
189 MakeTRANS( TRANS, _pitch_deg * SG_DEGREES_TO_RADIANS,
190 _roll_deg * SG_DEGREES_TO_RADIANS,
191 -_heading_deg * SG_DEGREES_TO_RADIANS,
194 // Given a vector pointing straight down (-Z), map into onto the
195 // local plane representing "horizontal". This should give us the
196 // local direction for moving "south".
198 sgSetVec3( minus_z, 0.0, 0.0, -1.0 );
200 sgmap_vec_onto_cur_surface_plane(_world_up, _relative_view_pos, minus_z,
202 sgNormalizeVec3(_surface_south);
204 // now calculate the surface east vector
206 sgNegateVec3(world_down, _world_up);
207 sgVectorProductVec3(_surface_east, _surface_south, world_down);
213 FGLocation::recalcPosition (double lon_deg, double lat_deg, double alt_ft) const
215 double sea_level_radius_m;
219 // Convert from geodetic to geocentric
221 sgGeodToGeoc(lat_deg * SGD_DEGREES_TO_RADIANS,
222 alt_ft * SG_FEET_TO_METER,
226 // Calculate the cartesian coordinates
227 // of point directly below at sea level.
228 // aka Zero Elevation Position
229 Point3D p = Point3D(lon_deg * SG_DEGREES_TO_RADIANS,
232 Point3D tmp = sgPolarToCart3d(p) - scenery.get_next_center();
233 sgSetVec3(_zero_elev_view_pos, tmp[0], tmp[1], tmp[2]);
235 // Calculate the absolute view position
236 // in fgfs coordinates.
237 // aka Absolute View Position
238 p.setz(p.radius() + alt_ft * SG_FEET_TO_METER);
239 tmp = sgPolarToCart3d(p);
240 sgdSetVec3(_absolute_view_pos, tmp[0], tmp[1], tmp[2]);
242 // Calculate the relative view position
243 // from the scenery center.
244 // aka Relative View Position
245 sgdVec3 scenery_center;
246 sgdSetVec3(scenery_center,
247 scenery.get_next_center().x(),
248 scenery.get_next_center().y(),
249 scenery.get_next_center().z());
251 sgdSubVec3(view_pos, _absolute_view_pos, scenery_center);
252 sgSetVec3(_relative_view_pos, view_pos);
257 FGLocation::update (int dt)