]> git.mxchange.org Git - flightgear.git/blob - src/Main/viewer.cxx
e1e7782fbd99e0ffc649b1be1f0ef77a2554159c
[flightgear.git] / src / Main / viewer.cxx
1 // viewer.cxx -- class for managing a viewer in the flightgear world.
2 //
3 // Written by Curtis Olson, started August 1997.
4 //                          overhaul started October 2000.
5 //
6 // Copyright (C) 1997 - 2000  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 "viewer.hxx"
40
41
42 \f
43 ////////////////////////////////////////////////////////////////////////
44 // Implementation of FGViewPoint.
45 ////////////////////////////////////////////////////////////////////////
46
47 FGViewPoint::FGViewPoint ()
48   : _dirty(true),
49     _lon_deg(0),
50     _lat_deg(0),
51     _alt_ft(0)
52 {
53 }
54
55 FGViewPoint::~FGViewPoint ()
56 {
57 }
58
59 void
60 FGViewPoint::setPosition (double lon_deg, double lat_deg, double alt_ft)
61 {
62   _dirty = true;
63   _lon_deg = lon_deg;
64   _lat_deg = lat_deg;
65   _alt_ft = alt_ft;
66 }
67
68 const double *
69 FGViewPoint::getAbsoluteViewPos () const
70 {
71   if (_dirty)
72     recalc();
73   return _absolute_view_pos;
74 }
75
76 const float *
77 FGViewPoint::getRelativeViewPos () const
78 {
79   if (_dirty)
80     recalc();
81   return _relative_view_pos;
82 }
83
84 const float *
85 FGViewPoint::getZeroElevViewPos () const
86 {
87   if (_dirty)
88     recalc();
89   return _zero_elev_view_pos;
90 }
91
92 void
93 FGViewPoint::recalc () const
94 {
95   double sea_level_radius_m;
96   double lat_geoc_rad;
97
98                                 // Convert from geodetic to geocentric
99                                 // coordinates.
100   sgGeodToGeoc(_lat_deg * SGD_DEGREES_TO_RADIANS,
101                _alt_ft * SG_FEET_TO_METER,
102                &sea_level_radius_m,
103                &lat_geoc_rad);
104
105                                 // Calculate the cartesian coordinates
106                                 // of point directly below at sea level.
107   Point3D p = Point3D(_lon_deg * SG_DEGREES_TO_RADIANS,
108                       lat_geoc_rad,
109                       sea_level_radius_m);
110   Point3D tmp = sgPolarToCart3d(p) - scenery.get_center();
111   sgSetVec3(_zero_elev_view_pos, tmp[0], tmp[1], tmp[2]);
112
113                                 // Calculate the absolute view position
114                                 // in fgfs coordinates.
115   p.setz(p.radius() + _alt_ft * SG_FEET_TO_METER);
116   tmp = sgPolarToCart3d(p);
117   sgdSetVec3(_absolute_view_pos, tmp[0], tmp[1], tmp[2]);
118
119                                 // Calculate the relative view position
120                                 // from the scenery center.
121   sgdVec3 scenery_center;
122   sgdSetVec3(scenery_center,
123              scenery.get_center().x(),
124              scenery.get_center().y(),
125              scenery.get_center().z());
126   sgdVec3 view_pos;
127   sgdSubVec3(view_pos, _absolute_view_pos, scenery_center);
128   sgSetVec3(_relative_view_pos, view_pos);
129 }
130
131
132 \f
133 ////////////////////////////////////////////////////////////////////////
134 // Implementation of FGViewer.
135 ////////////////////////////////////////////////////////////////////////
136
137 // Constructor
138 FGViewer::FGViewer( void ):
139     scalingType(FG_SCALING_MAX),
140     fov(55.0),
141     view_offset(0.0),
142     goal_view_offset(0.0),
143     view_tilt(0.0),
144     goal_view_tilt(0.0)
145 {
146     sgSetVec3( pilot_offset, 0.0, 0.0, 0.0 );
147     sgdZeroVec3(geod_view_pos);
148     sgdZeroVec3(abs_view_pos);
149     sea_level_radius = SG_EQUATORIAL_RADIUS_M; 
150     //a reasonable guess for init, so that the math doesn't blow up
151 }
152
153
154 // Destructor
155 FGViewer::~FGViewer( void ) {
156 }
157
158 void
159 FGViewer::init ()
160 {
161 }
162
163 void
164 FGViewer::bind ()
165 {
166 }
167
168 void
169 FGViewer::unbind ()
170 {
171 }
172
173 double
174 FGViewer::get_h_fov()
175 {
176     switch (scalingType) {
177     case FG_SCALING_WIDTH:  // h_fov == fov
178         return fov;
179     case FG_SCALING_MAX:
180         if (aspect_ratio < 1.0) {
181             // h_fov == fov
182             return fov;
183         } else {
184             // v_fov == fov
185             return atan(tan(fov/2 * SG_DEGREES_TO_RADIANS) / aspect_ratio) *
186                 SG_RADIANS_TO_DEGREES * 2;
187         }
188     default:
189         assert(false);
190     }
191 }
192
193 double
194 FGViewer::get_v_fov()
195 {
196     switch (scalingType) {
197     case FG_SCALING_WIDTH:  // h_fov == fov
198         return atan(tan(fov/2 * SG_DEGREES_TO_RADIANS) * aspect_ratio) *
199             SG_RADIANS_TO_DEGREES * 2;
200     case FG_SCALING_MAX:
201         if (aspect_ratio < 1.0) {
202             // h_fov == fov
203             return atan(tan(fov/2 * SG_DEGREES_TO_RADIANS) * aspect_ratio) *
204                 SG_RADIANS_TO_DEGREES * 2;
205         } else {
206             // v_fov == fov
207             return fov;
208         }
209     default:
210         assert(false);
211     }
212 }
213
214 void
215 FGViewer::update (int dt)
216 {
217   int i;
218   for ( i = 0; i < dt; i++ ) {
219     if ( fabs(get_goal_view_offset() - get_view_offset()) < 0.05 ) {
220       set_view_offset( get_goal_view_offset() );
221       break;
222     } else {
223       // move current_view.view_offset towards
224       // current_view.goal_view_offset
225       if ( get_goal_view_offset() > get_view_offset() )
226         {
227           if ( get_goal_view_offset() - get_view_offset() < SGD_PI ){
228             inc_view_offset( 0.01 );
229           } else {
230             inc_view_offset( -0.01 );
231           }
232         } else {
233           if ( get_view_offset() - get_goal_view_offset() < SGD_PI ){
234             inc_view_offset( -0.01 );
235           } else {
236             inc_view_offset( 0.01 );
237           }
238         }
239       if ( get_view_offset() > SGD_2PI ) {
240         inc_view_offset( -SGD_2PI );
241       } else if ( get_view_offset() < 0 ) {
242         inc_view_offset( SGD_2PI );
243       }
244     }
245   }
246
247   for ( i = 0; i < dt; i++ ) {
248     if ( fabs(get_goal_view_tilt() - get_view_tilt()) < 0.05 ) {
249       set_view_tilt( get_goal_view_tilt() );
250       break;
251     } else {
252       // move current_view.view_tilt towards
253       // current_view.goal_view_tilt
254       if ( get_goal_view_tilt() > get_view_tilt() )
255         {
256           if ( get_goal_view_tilt() - get_view_tilt() < SGD_PI ){
257             inc_view_tilt( 0.01 );
258           } else {
259             inc_view_tilt( -0.01 );
260           }
261         } else {
262           if ( get_view_tilt() - get_goal_view_tilt() < SGD_PI ){
263             inc_view_tilt( -0.01 );
264           } else {
265             inc_view_tilt( 0.01 );
266           }
267         }
268       if ( get_view_tilt() > SGD_2PI ) {
269         inc_view_tilt( -SGD_2PI );
270       } else if ( get_view_tilt() < 0 ) {
271         inc_view_tilt( SGD_2PI );
272       }
273     }
274   }
275 }