]> git.mxchange.org Git - flightgear.git/blob - src/Main/viewmgr.cxx
Centralized most view-management code in FGViewMgr. It's still a
[flightgear.git] / src / Main / viewmgr.cxx
1 // viewmgr.cxx -- class for managing all the views in the flightgear world.
2 //
3 // Written by Curtis Olson, started October 2000.
4 //
5 // Copyright (C) 2000  Curtis L. Olson  - curt@flightgear.org
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 // General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 //
21 // $Id$
22
23 #include <plib/sg.h>
24
25 #include <GUI/sgVec3Slider.hxx> // FIXME: this should NOT be needed
26
27 #include "viewmgr.hxx"
28 #include "fg_props.hxx"
29
30
31 // Constructor
32 FGViewMgr::FGViewMgr( void ) :
33   axis_long(0),
34   axis_lat(0),
35   current(0)
36 {
37 }
38
39
40 // Destructor
41 FGViewMgr::~FGViewMgr( void ) {
42 }
43
44 void
45 FGViewMgr::init ()
46 {
47   add_view(new FGViewerRPH);
48   add_view(new FGViewerLookAt);
49 }
50
51 typedef double (FGViewMgr::*double_getter)() const;
52
53 void
54 FGViewMgr::bind ()
55 {
56   fgTie("/sim/view/offset-deg", this,
57         &FGViewMgr::getViewOffset_deg, &FGViewMgr::setViewOffset_deg);
58   fgSetArchivable("/sim/view/offset-deg");
59   fgTie("/sim/view/goal-offset-deg", this,
60         &FGViewMgr::getGoalViewOffset_deg, &FGViewMgr::setGoalViewOffset_deg);
61   fgSetArchivable("/sim/view/goal-offset-deg");
62   fgTie("/sim/view/tilt-deg", this,
63         &FGViewMgr::getViewTilt_deg, &FGViewMgr::setViewTilt_deg);
64   fgSetArchivable("/sim/view/tilt-deg");
65   fgTie("/sim/view/goal-tilt-deg", this,
66         &FGViewMgr::getGoalViewTilt_deg, &FGViewMgr::setGoalViewTilt_deg);
67   fgSetArchivable("/sim/view/goal-tilt-deg");
68   fgTie("/sim/view/pilot/x-offset-m", this,
69         &FGViewMgr::getPilotXOffset_m, &FGViewMgr::setPilotXOffset_m);
70   fgSetArchivable("/sim/view/pilot/x-offset-m");
71   fgTie("/sim/view/pilot/y-offset-m", this,
72         &FGViewMgr::getPilotYOffset_m, &FGViewMgr::setPilotYOffset_m);
73   fgSetArchivable("/sim/view/pilot/y-offset-m");
74   fgTie("/sim/view/pilot/z-offset-m", this,
75         &FGViewMgr::getPilotZOffset_m, &FGViewMgr::setPilotZOffset_m);
76   fgSetArchivable("/sim/view/pilot/z-offset-m");
77   fgTie("/sim/field-of-view", this,
78         &FGViewMgr::getFOV_deg, &FGViewMgr::setFOV_deg);
79   fgSetArchivable("/sim/field-of-view");
80   fgTie("/sim/view/axes/long", this,
81         (double_getter)0, &FGViewMgr::setViewAxisLong);
82   fgTie("/sim/view/axes/lat", this,
83         (double_getter)0, &FGViewMgr::setViewAxisLat);
84 }
85
86 void
87 FGViewMgr::unbind ()
88 {
89   fgUntie("/sim/view/offset-deg");
90   fgUntie("/sim/view/goal-offset-deg");
91   fgUntie("/sim/view/tilt-deg");
92   fgUntie("/sim/view/goal-tilt-deg");
93   fgUntie("/sim/view/pilot/x-offset-m");
94   fgUntie("/sim/view/pilot/y-offset-m");
95   fgUntie("/sim/view/pilot/z-offset-m");
96   fgUntie("/sim/field-of-view");
97   fgUntie("/sim/view/axes/long");
98   fgUntie("/sim/view/axes/lat");
99 }
100
101 void
102 FGViewMgr::update (int dt)
103 {
104   FGViewer * view = get_current_view();
105   if (view == 0)
106     return;
107
108                                 // Grab some values we'll need.
109   double lon_rad = fgGetDouble("/position/longitude-deg")
110     * SGD_DEGREES_TO_RADIANS;
111   double lat_rad = fgGetDouble("/position/latitude-deg")
112     * SGD_DEGREES_TO_RADIANS;
113   double alt_m = fgGetDouble("/position/altitude-ft")
114     * SG_FEET_TO_METER;
115   double roll_rad = fgGetDouble("/orientation/roll-deg")
116     * SGD_DEGREES_TO_RADIANS;
117   double pitch_rad = fgGetDouble("/orientation/pitch-deg")
118     * SGD_DEGREES_TO_RADIANS;
119   double heading_rad = fgGetDouble("/orientation/heading-deg")
120     * SGD_DEGREES_TO_RADIANS;
121
122                                 // Set up the pilot view
123   FGViewerRPH *pilot_view = (FGViewerRPH *)get_view( 0 );
124   pilot_view ->set_geod_view_pos(lon_rad, lat_rad, alt_m);
125   pilot_view->set_rph(roll_rad, pitch_rad, heading_rad);
126   if (fgGetString("/sim/flight-model") == "ada") {
127     //+ve x is aft, +ve z is up (see viewer.hxx)
128     pilot_view->set_pilot_offset( -5.0, 0.0, 1.0 ); 
129   }
130
131                                 // Set up the chase view
132
133                                 // FIXME: the matrix math belongs in
134                                 // the viewer, not here.
135   FGViewerLookAt *chase_view = (FGViewerLookAt *)get_view( 1 );
136
137   sgVec3 po;            // chase view pilot_offset
138   sgVec3 wup;           // chase view world up
139   sgSetVec3( po, 0.0, 0.0, 100.0 );
140   sgCopyVec3( wup, pilot_view->get_world_up() );
141   sgMat4 CXFM;          // chase view + pilot offset xform
142   sgMakeRotMat4( CXFM,
143                  chase_view->get_view_offset() * SGD_RADIANS_TO_DEGREES -
144                  heading_rad * SGD_RADIANS_TO_DEGREES,
145                  wup );
146   sgVec3 npo;           // new pilot offset after rotation
147   sgVec3 *pPO = PilotOffsetGet();
148   sgXformVec3( po, *pPO, pilot_view->get_UP() );
149   sgXformVec3( npo, po, CXFM );
150
151   chase_view->set_geod_view_pos(lon_rad, lat_rad, alt_m);
152   chase_view->set_pilot_offset( npo[0], npo[1], npo[2] );
153   chase_view->set_view_forward( pilot_view->get_view_pos() ); 
154   chase_view->set_view_up( wup );
155
156                                 // Update the current view
157   do_axes();
158   view->update(dt);
159 }
160
161 double
162 FGViewMgr::getViewOffset_deg () const
163 {
164   const FGViewer * view = get_current_view();
165   return (view == 0 ? 0 : view->get_view_offset() * SGD_RADIANS_TO_DEGREES);
166 }
167
168 void
169 FGViewMgr::setViewOffset_deg (double offset)
170 {
171   FGViewer * view = get_current_view();
172   if (view != 0)
173     view->set_view_offset(offset * SGD_DEGREES_TO_RADIANS);
174   std::cout << "View offset is now " << offset << std::endl;
175 }
176
177 double
178 FGViewMgr::getGoalViewOffset_deg () const
179 {
180   const FGViewer * view = get_current_view();
181   return (view == 0 ? 0 : view->get_goal_view_offset() * SGD_RADIANS_TO_DEGREES);
182 }
183
184 void
185 FGViewMgr::setGoalViewOffset_deg (double offset)
186 {
187   FGViewer * view = get_current_view();
188   if (view != 0)
189     view->set_goal_view_offset(offset * SGD_DEGREES_TO_RADIANS);
190   std::cout << "Goal view offset is now " << offset << std::endl;
191 }
192
193 double
194 FGViewMgr::getViewTilt_deg () const
195 {
196   const FGViewer * view = get_current_view();
197   return (view == 0 ? 0 : view->get_view_tilt() * SGD_RADIANS_TO_DEGREES);
198 }
199
200 void
201 FGViewMgr::setViewTilt_deg (double tilt)
202 {
203   FGViewer * view = get_current_view();
204   if (view != 0)
205     view->set_view_tilt(tilt * SGD_DEGREES_TO_RADIANS);
206 }
207
208 double
209 FGViewMgr::getGoalViewTilt_deg () const
210 {
211   const FGViewer * view = get_current_view();
212   return (view == 0 ? 0 : view->get_goal_view_tilt() * SGD_RADIANS_TO_DEGREES);
213 }
214
215 void
216 FGViewMgr::setGoalViewTilt_deg (double tilt)
217 {
218   FGViewer * view = get_current_view();
219   if (view != 0)
220     view->set_goal_view_tilt(tilt * SGD_DEGREES_TO_RADIANS);
221 }
222
223 double
224 FGViewMgr::getPilotXOffset_m () const
225 {
226                                 // FIXME: hard-coded pilot view position
227   const FGViewer * pilot_view = get_view(0);
228   if (pilot_view != 0) {
229     float * offset = ((FGViewer *)pilot_view)->get_pilot_offset();
230     return offset[0];
231   } else {
232     return 0;
233   }
234 }
235
236 void
237 FGViewMgr::setPilotXOffset_m (double x)
238 {
239                                 // FIXME: hard-coded pilot view position
240   FGViewer * pilot_view = get_view(0);
241   if (pilot_view != 0) {
242     float * offset = pilot_view->get_pilot_offset();
243     pilot_view->set_pilot_offset(x, offset[1], offset[2]);
244   }
245 }
246
247 double
248 FGViewMgr::getPilotYOffset_m () const
249 {
250                                 // FIXME: hard-coded pilot view position
251   const FGViewer * pilot_view = get_view(0);
252   if (pilot_view != 0) {
253     float * offset = ((FGViewer *)pilot_view)->get_pilot_offset();
254     return offset[1];
255   } else {
256     return 0;
257   }
258 }
259
260 void
261 FGViewMgr::setPilotYOffset_m (double y)
262 {
263                                 // FIXME: hard-coded pilot view position
264   FGViewer * pilot_view = get_view(0);
265   if (pilot_view != 0) {
266     float * offset = pilot_view->get_pilot_offset();
267     pilot_view->set_pilot_offset(offset[0], y, offset[2]);
268   }
269 }
270
271 double
272 FGViewMgr::getPilotZOffset_m () const
273 {
274                                 // FIXME: hard-coded pilot view position
275   const FGViewer * pilot_view = get_view(0);
276   if (pilot_view != 0) {
277     float * offset = ((FGViewer *)pilot_view)->get_pilot_offset();
278     return offset[2];
279   } else {
280     return 0;
281   }
282 }
283
284 void
285 FGViewMgr::setPilotZOffset_m (double z)
286 {
287                                 // FIXME: hard-coded pilot view position
288   FGViewer * pilot_view = get_view(0);
289   if (pilot_view != 0) {
290     float * offset = pilot_view->get_pilot_offset();
291     pilot_view->set_pilot_offset(offset[0], offset[1], z);
292   }
293 }
294
295 double
296 FGViewMgr::getFOV_deg () const
297 {
298   const FGViewer * view = get_current_view();
299   return (view == 0 ? 0 : view->get_fov());
300 }
301
302 void
303 FGViewMgr::setFOV_deg (double fov)
304 {
305   FGViewer * view = get_current_view();
306   if (view != 0)
307     view->set_fov(fov);
308 }
309
310 void
311 FGViewMgr::setViewAxisLong (double axis)
312 {
313   axis_long = axis;
314 }
315
316 void
317 FGViewMgr::setViewAxisLat (double axis)
318 {
319   axis_lat = axis;
320 }
321
322 void
323 FGViewMgr::do_axes ()
324 {
325                                 // Take no action when hat is centered
326   if ( ( axis_long <  0.01 ) &&
327        ( axis_long > -0.01 ) &&
328        ( axis_lat  <  0.01 ) &&
329        ( axis_lat  > -0.01 )
330      )
331     return;
332
333   double viewDir = 999;
334
335   /* Do all the quick and easy cases */
336   if (axis_long < 0) {          // Longitudinal axis forward
337     if (axis_lat == axis_long)
338       viewDir = 45;
339     else if (axis_lat == - axis_long)
340       viewDir = 315;
341     else if (axis_lat == 0)
342       viewDir = 0;
343   } else if (axis_long > 0) {   // Longitudinal axis backward
344     if (axis_lat == - axis_long)
345       viewDir = 135;
346     else if (axis_lat == axis_long)
347       viewDir = 225;
348     else if (axis_lat == 0)
349       viewDir = 180;
350   } else if (axis_long == 0) {  // Longitudinal axis neutral
351     if (axis_lat < 0)
352       viewDir = 90;
353     else if (axis_lat > 0)
354       viewDir = 270;
355     else return; /* And assertion failure maybe? */
356   }
357
358                                 // Do all the difficult cases
359   if ( viewDir > 900 )
360     viewDir = SGD_RADIANS_TO_DEGREES * atan2 ( -axis_lat, -axis_long );
361   if ( viewDir < -1 ) viewDir += 360;
362
363   get_current_view()->set_goal_view_offset(viewDir*SGD_DEGREES_TO_RADIANS);
364 }