]> git.mxchange.org Git - flightgear.git/blob - src/Main/location.cxx
Patch from Jim Wilson:
[flightgear.git] / src / Main / location.cxx
1 // location.cxx -- class for determining model location in the flightgear world.
2 //
3 // Written by Jim Wilson, David Megginson, started April 2002.
4 // Based largely on code by Curtis Olson and Norman Vine.
5 //
6 // Copyright (C) 2002  Curtis L. Olson - curt@flightgear.org
7 //
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.
12 //
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.
17 //
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.
21 //
22 // $Id$
23
24
25 #include <simgear/compiler.h>
26
27 #ifdef HAVE_CONFIG_H
28 #  include <config.h>
29 #endif
30
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
37 #include <Scenery/scenery.hxx>
38
39 #include <simgear/math/vector.hxx>
40 /*
41 #include "globals.hxx"
42 */
43
44 #include "location.hxx"
45
46
47 /**
48  * make model transformation Matrix - based on optimizations by NHV
49  */
50 static void MakeTRANS( sgMat4 dst, const double Theta,
51                         const double Phi, const double Psi, 
52                         const sgMat4 UP)
53 {
54     SGfloat cosTheta = (SGfloat) cos(Theta);
55     SGfloat sinTheta = (SGfloat) sin(Theta);
56     SGfloat cosPhi   = (SGfloat) cos(Phi);
57     SGfloat sinPhi   = (SGfloat) sin(Phi);
58     SGfloat sinPsi   = (SGfloat) sin(Psi) ;
59     SGfloat cosPsi   = (SGfloat) cos(Psi) ;
60
61     sgMat4 tmp;
62         
63     tmp[0][0] = cosPhi * cosTheta;
64     tmp[0][1] = sinPhi * cosPsi + cosPhi * -sinTheta * -sinPsi;
65     tmp[0][2] = sinPhi * sinPsi + cosPhi * -sinTheta * cosPsi;
66
67     tmp[1][0] = -sinPhi * cosTheta;
68     tmp[1][1] = cosPhi * cosPsi + -sinPhi * -sinTheta * -sinPsi;
69     tmp[1][2] = cosPhi * sinPsi + -sinPhi * -sinTheta * cosPsi;
70         
71     tmp[2][0] = sinTheta;
72     tmp[2][1] = cosTheta * -sinPsi;
73     tmp[2][2] = cosTheta * cosPsi;
74         
75     float a = UP[0][0];
76     float b = UP[1][0];
77     float c = UP[2][0];
78     dst[2][0] = a*tmp[0][0] + b*tmp[0][1] + c*tmp[0][2] ;
79     dst[1][0] = a*tmp[1][0] + b*tmp[1][1] + c*tmp[1][2] ;
80     dst[0][0] = -(a*tmp[2][0] + b*tmp[2][1] + c*tmp[2][2]) ;
81     dst[3][0] = SG_ZERO ;
82
83     a = UP[0][1];
84     b = UP[1][1];
85     c = UP[2][1];
86     dst[2][1] = a*tmp[0][0] + b*tmp[0][1] + c*tmp[0][2] ;
87     dst[1][1] = a*tmp[1][0] + b*tmp[1][1] + c*tmp[1][2] ;
88     dst[0][1] = -(a*tmp[2][0] + b*tmp[2][1] + c*tmp[2][2]) ;
89     dst[3][1] = SG_ZERO ;
90
91     a = UP[0][2];
92     c = UP[2][2];
93     dst[2][2] = a*tmp[0][0] + c*tmp[0][2] ;
94     dst[1][2] = a*tmp[1][0] + c*tmp[1][2] ;
95     dst[0][2] = -(a*tmp[2][0] + c*tmp[2][2]) ;
96     dst[3][2] = SG_ZERO ;
97
98     dst[2][3] = SG_ZERO ;
99     dst[1][3] = SG_ZERO ;
100     dst[0][3] = SG_ZERO ;
101     dst[3][3] = SG_ONE ;
102
103 }
104
105
106 ////////////////////////////////////////////////////////////////////////
107 // Implementation of FGLocation.
108 ////////////////////////////////////////////////////////////////////////
109
110 // Constructor
111 FGLocation::FGLocation( void ):
112     _dirty(true),
113     _lon_deg(0),
114     _lat_deg(0),
115     _alt_ft(0),
116     _roll_deg(0),
117     _pitch_deg(0),
118     _heading_deg(0)
119 {
120     sgdZeroVec3(_absolute_view_pos);
121 }
122
123
124 // Destructor
125 FGLocation::~FGLocation( void ) {
126 }
127
128 void
129 FGLocation::init ()
130 {
131 }
132
133 void
134 FGLocation::bind ()
135 {
136 }
137
138 void
139 FGLocation::unbind ()
140 {
141 }
142
143 void
144 FGLocation::setPosition (double lon_deg, double lat_deg, double alt_ft)
145 {
146   _dirty = true;
147   _lon_deg = lon_deg;
148   _lat_deg = lat_deg;
149   _alt_ft = alt_ft;
150 }
151
152 void
153 FGLocation::setOrientation (double roll_deg, double pitch_deg, double heading_deg)
154 {
155   _dirty = true;
156   _roll_deg = roll_deg;
157   _pitch_deg = pitch_deg;
158   _heading_deg = heading_deg;
159 }
160
161 double *
162 FGLocation::get_absolute_view_pos () 
163 {
164   if (_dirty)
165     recalc();
166   return _absolute_view_pos;
167 }
168
169 float *
170 FGLocation::getRelativeViewPos () 
171 {
172   if (_dirty)
173     recalc();
174   return _relative_view_pos;
175 }
176
177 float *
178 FGLocation::getZeroElevViewPos () 
179 {
180   if (_dirty)
181     recalc();
182   return _zero_elev_view_pos;
183 }
184
185
186 // recalc() is done every time one of the setters is called (making the 
187 // cached data "dirty") on the next "get".  It calculates all the outputs 
188 // for viewer.
189 void
190 FGLocation::recalc ()
191 {
192
193   recalcPosition( _lon_deg, _lat_deg, _alt_ft );
194
195   // Make the world up rotation matrix for eye positioin...
196   sgMakeRotMat4( UP, _lon_deg, 0.0, -_lat_deg );
197
198
199   // get the world up radial vector from planet center for output
200   sgSetVec3( _world_up, UP[0][0], UP[0][1], UP[0][2] );
201
202   // Creat local matrix with current geodetic position.  Converting
203   // the orientation (pitch/roll/heading) to vectors.
204   MakeTRANS( TRANS, _pitch_deg * SG_DEGREES_TO_RADIANS,
205                       _roll_deg * SG_DEGREES_TO_RADIANS,
206                       -_heading_deg * SG_DEGREES_TO_RADIANS,
207                       UP);
208
209   // Given a vector pointing straight down (-Z), map into onto the
210   // local plane representing "horizontal".  This should give us the
211   // local direction for moving "south".
212   sgVec3 minus_z;
213   sgSetVec3( minus_z, 0.0, 0.0, -1.0 );
214
215   sgmap_vec_onto_cur_surface_plane(_world_up, _relative_view_pos, minus_z,
216                                      _surface_south);
217   sgNormalizeVec3(_surface_south);
218
219   // now calculate the surface east vector
220   sgVec3 world_down;
221   sgNegateVec3(world_down, _world_up);
222   sgVectorProductVec3(_surface_east, _surface_south, world_down);
223
224   set_clean();
225 }
226
227 void
228 FGLocation::recalcPosition (double lon_deg, double lat_deg, double alt_ft) const
229 {
230   double sea_level_radius_m;
231   double lat_geoc_rad;
232
233
234                                 // Convert from geodetic to geocentric
235                                 // coordinates.
236   sgGeodToGeoc(lat_deg * SGD_DEGREES_TO_RADIANS,
237                alt_ft * SG_FEET_TO_METER,
238                &sea_level_radius_m,
239                &lat_geoc_rad);
240
241                                 // Calculate the cartesian coordinates
242                                 // of point directly below at sea level.
243                                 // aka Zero Elevation Position
244   Point3D p = Point3D(lon_deg * SG_DEGREES_TO_RADIANS,
245                       lat_geoc_rad,
246                       sea_level_radius_m);
247   Point3D tmp = sgPolarToCart3d(p) - scenery.get_center();
248   sgSetVec3(_zero_elev_view_pos, tmp[0], tmp[1], tmp[2]);
249
250                                 // Calculate the absolute view position
251                                 // in fgfs coordinates.
252                                 // aka Absolute View Position
253   p.setz(p.radius() + alt_ft * SG_FEET_TO_METER);
254   tmp = sgPolarToCart3d(p);
255   sgdSetVec3(_absolute_view_pos, tmp[0], tmp[1], tmp[2]);
256
257                                 // Calculate the relative view position
258                                 // from the scenery center.
259                                 // aka Relative View Position
260   sgdVec3 scenery_center;
261   sgdSetVec3(scenery_center,
262              scenery.get_center().x(),
263              scenery.get_center().y(),
264              scenery.get_center().z());
265   sgdVec3 view_pos;
266   sgdSubVec3(view_pos, _absolute_view_pos, scenery_center);
267   sgSetVec3(_relative_view_pos, view_pos);
268
269 }
270
271 void
272 FGLocation::update (int dt)
273 {
274 }
275
276
277
278
279