1 // location.cxx -- class for determining model location in the flightgear world.
3 // Written by Jim Wilson, David Megginson, started April 2002.
4 // Based largely on code by Curtis Olson and Norman Vine.
6 // Copyright (C) 2002 Curtis L. Olson - curt@flightgear.org
8 // This program is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU General Public License as
10 // published by the Free Software Foundation; either version 2 of the
11 // License, or (at your option) any later version.
13 // This program is distributed in the hope that it will be useful, but
14 // WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // General Public License for more details.
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the Free Software
20 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #include <simgear/compiler.h>
28 # include <simgear_config.h>
31 #include <simgear/debug/logstream.hxx>
32 #include <simgear/constants.h>
33 #include <simgear/math/point3d.hxx>
34 #include <simgear/math/polar3d.hxx>
35 #include <simgear/math/sg_geodesy.hxx>
36 #include <simgear/math/vector.hxx>
38 // #include <Scenery/scenery.hxx>
39 // #include "globals.hxx"
41 #include "location.hxx"
45 * make model transformation Matrix - based on optimizations by NHV
47 static void MakeTRANS( sgMat4 dst, const double Theta,
48 const double Phi, const double Psi,
51 SGfloat cosTheta = (SGfloat) cos(Theta);
52 SGfloat sinTheta = (SGfloat) sin(Theta);
53 SGfloat cosPhi = (SGfloat) cos(Phi);
54 SGfloat sinPhi = (SGfloat) sin(Phi);
55 SGfloat sinPsi = (SGfloat) sin(Psi) ;
56 SGfloat cosPsi = (SGfloat) cos(Psi) ;
60 tmp[0][0] = cosPhi * cosTheta;
61 tmp[0][1] = sinPhi * cosPsi + cosPhi * -sinTheta * -sinPsi;
62 tmp[0][2] = sinPhi * sinPsi + cosPhi * -sinTheta * cosPsi;
64 tmp[1][0] = -sinPhi * cosTheta;
65 tmp[1][1] = cosPhi * cosPsi + -sinPhi * -sinTheta * -sinPsi;
66 tmp[1][2] = cosPhi * sinPsi + -sinPhi * -sinTheta * cosPsi;
69 tmp[2][1] = cosTheta * -sinPsi;
70 tmp[2][2] = cosTheta * cosPsi;
75 dst[2][0] = a*tmp[0][0] + b*tmp[0][1] + c*tmp[0][2] ;
76 dst[1][0] = a*tmp[1][0] + b*tmp[1][1] + c*tmp[1][2] ;
77 dst[0][0] = -(a*tmp[2][0] + b*tmp[2][1] + c*tmp[2][2]) ;
83 dst[2][1] = a*tmp[0][0] + b*tmp[0][1] + c*tmp[0][2] ;
84 dst[1][1] = a*tmp[1][0] + b*tmp[1][1] + c*tmp[1][2] ;
85 dst[0][1] = -(a*tmp[2][0] + b*tmp[2][1] + c*tmp[2][2]) ;
90 dst[2][2] = a*tmp[0][0] + c*tmp[0][2] ;
91 dst[1][2] = a*tmp[1][0] + c*tmp[1][2] ;
92 dst[0][2] = -(a*tmp[2][0] + c*tmp[2][2]) ;
103 ////////////////////////////////////////////////////////////////////////
104 // Implementation of SGLocation.
105 ////////////////////////////////////////////////////////////////////////
108 SGLocation::SGLocation( void ):
119 sgdZeroVec3(_absolute_view_pos);
120 sgZeroVec3(_relative_view_pos);
121 sgZeroVec3(_zero_elev_view_pos);
122 sgMakeRotMat4( UP, 0.0, 0.0, 0.0 );
123 sgMakeRotMat4( TRANS, 0.0, 0.0, 0.0 );
128 SGLocation::~SGLocation( void ) {
142 SGLocation::unbind ()
147 SGLocation::setPosition (double lon_deg, double lat_deg, double alt_ft)
156 SGLocation::setOrientation (double roll_deg, double pitch_deg, double heading_deg)
159 _roll_deg = roll_deg;
160 _pitch_deg = pitch_deg;
161 _heading_deg = heading_deg;
165 SGLocation::get_absolute_view_pos( const Point3D scenery_center )
168 recalc( scenery_center );
170 return _absolute_view_pos;
174 SGLocation::getRelativeViewPos( const Point3D scenery_center )
177 recalc( scenery_center );
179 return _relative_view_pos;
183 SGLocation::getZeroElevViewPos( const Point3D scenery_center )
186 recalc( scenery_center );
188 return _zero_elev_view_pos;
192 // recalc() is done every time one of the setters is called (making the
193 // cached data "dirty") on the next "get". It calculates all the outputs
196 SGLocation::recalc( const Point3D scenery_center )
199 recalcPosition( _lon_deg, _lat_deg, _alt_ft, scenery_center );
201 // Make the world up rotation matrix for eye positioin...
202 sgMakeRotMat4( UP, _lon_deg, 0.0, -_lat_deg );
205 // get the world up radial vector from planet center for output
206 sgSetVec3( _world_up, UP[0][0], UP[0][1], UP[0][2] );
208 // Creat local matrix with current geodetic position. Converting
209 // the orientation (pitch/roll/heading) to vectors.
210 MakeTRANS( TRANS, _pitch_deg * SG_DEGREES_TO_RADIANS,
211 _roll_deg * SG_DEGREES_TO_RADIANS,
212 -_heading_deg * SG_DEGREES_TO_RADIANS,
215 // Given a vector pointing straight down (-Z), map into onto the
216 // local plane representing "horizontal". This should give us the
217 // local direction for moving "south".
219 sgSetVec3( minus_z, 0.0, 0.0, -1.0 );
221 sgmap_vec_onto_cur_surface_plane(_world_up, _relative_view_pos, minus_z,
223 sgNormalizeVec3(_surface_south);
225 // now calculate the surface east vector
227 sgNegateVec3(world_down, _world_up);
228 sgVectorProductVec3(_surface_east, _surface_south, world_down);
234 SGLocation::recalcPosition( double lon_deg, double lat_deg, double alt_ft,
235 const Point3D scenery_center ) const
237 double sea_level_radius_m;
241 // Convert from geodetic to geocentric
243 sgGeodToGeoc(lat_deg * SGD_DEGREES_TO_RADIANS,
244 alt_ft * SG_FEET_TO_METER,
248 // Calculate the cartesian coordinates
249 // of point directly below at sea level.
250 // aka Zero Elevation Position
251 Point3D p = Point3D(lon_deg * SG_DEGREES_TO_RADIANS,
254 Point3D tmp = sgPolarToCart3d(p) - _tile_center;
255 sgSetVec3(_zero_elev_view_pos, tmp[0], tmp[1], tmp[2]);
257 // Calculate the absolute view position
258 // in fgfs coordinates.
259 // aka Absolute View Position
260 p.setz(p.radius() + alt_ft * SG_FEET_TO_METER);
261 tmp = sgPolarToCart3d(p);
262 sgdSetVec3(_absolute_view_pos, tmp[0], tmp[1], tmp[2]);
264 // Calculate the relative view position
265 // from the scenery center.
266 // aka Relative View Position
268 // FIXME: view position should ONLY be calculated in the viewer...
269 // Anything else should calculate their own positions relative to the
270 // viewer's tile_center.
273 scenery_center.x(), scenery_center.y(), scenery_center.z() );
275 sgdSubVec3(view_pos, _absolute_view_pos, center);
276 sgSetVec3(_relative_view_pos, view_pos);
281 SGLocation::update (int dt)