]> git.mxchange.org Git - flightgear.git/blob - src/Main/viewmgr.cxx
Added static port system and a new altimeter model connected to it.
[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 //   partially rewritten by Jim Wilson March 2002
5 //
6 // Copyright (C) 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 #include <string.h>             // strcmp
25
26 #include <plib/sg.h>
27
28 #include "viewmgr.hxx"
29 #include "fg_props.hxx"
30
31
32 // Constructor
33 FGViewMgr::FGViewMgr( void ) :
34   axis_long(0),
35   axis_lat(0),
36   current(0)
37 {
38 }
39
40
41 // Destructor
42 FGViewMgr::~FGViewMgr( void ) {
43 }
44
45 void
46 FGViewMgr::init ()
47 {
48   char stridx [ 20 ];
49   string viewpath, nodepath, strdata;
50   bool from_model = false;
51   bool at_model = false;
52   int from_model_index = 0;
53   int at_model_index = 0;
54   double x_offset_m, y_offset_m, z_offset_m;
55   double near_m;
56
57   for (int i = 0; i < fgGetInt("/sim/number-views"); i++) {
58     viewpath = "/sim/view";
59     sprintf(stridx, "[%d]", i);
60     viewpath += stridx;
61
62     // find out what type of view this is...
63     nodepath = viewpath;
64     nodepath += "/type";
65     strdata = fgGetString(nodepath.c_str());
66
67     // FIXME:
68     // this is assumed to be an aircraft model...we will need to read
69     // model-from-type as well.
70     // find out if this is a model we are looking from...
71     nodepath = viewpath;
72     nodepath += "/config/from-model";
73     from_model = fgGetBool(nodepath.c_str());
74
75     // get model index (which model)
76     if (from_model) {
77       nodepath = viewpath;
78       nodepath += "/config/from-model-idx";
79       from_model_index = fgGetInt(nodepath.c_str());     
80     }
81
82     if ( strcmp("lookat",strdata.c_str()) == 0 ) {
83       // find out if this is a model we are looking at...
84       nodepath = viewpath;
85       nodepath += "/config/at-model";
86       at_model = fgGetBool(nodepath.c_str());
87
88       // get model index (which model)
89       if (at_model) {
90         nodepath = viewpath;
91         nodepath += "/config/at-model-idx";
92         at_model_index = fgGetInt(nodepath.c_str());     
93       }
94     }
95
96     nodepath = viewpath;
97     nodepath += "/config/x-offset-m";
98     x_offset_m = fgGetDouble(nodepath.c_str());
99     nodepath = viewpath;
100     nodepath += "/config/y-offset-m";
101     y_offset_m = fgGetDouble(nodepath.c_str());
102     nodepath = viewpath;
103     nodepath += "/config/z-offset-m";
104     z_offset_m = fgGetDouble(nodepath.c_str());
105
106     nodepath = viewpath;
107     nodepath += "/config/ground-level-nearplane-m";
108     near_m = fgGetDouble(nodepath.c_str());
109
110     // supporting two types now "lookat" = 1 and "lookfrom" = 0
111     if ( strcmp("lookat",strdata.c_str()) == 0 )
112       add_view(new FGViewer ( FG_LOOKAT, from_model, from_model_index,
113                               at_model, at_model_index, x_offset_m, y_offset_m,
114                               z_offset_m, near_m ));
115     else
116       add_view(new FGViewer ( FG_LOOKFROM, from_model, from_model_index, false,
117                               0, x_offset_m, y_offset_m, z_offset_m, near_m ));
118
119   }
120
121   copyToCurrent();
122   
123 }
124
125 typedef double (FGViewMgr::*double_getter)() const;
126
127 void
128 FGViewMgr::bind ()
129 {
130   // these are bound to the current view properties
131   fgTie("/sim/current-view/heading-offset-deg", this,
132         &FGViewMgr::getViewOffset_deg, &FGViewMgr::setViewOffset_deg);
133   fgSetArchivable("/sim/current-view/heading-offset-deg");
134   fgTie("/sim/current-view/goal-heading-offset-deg", this,
135         &FGViewMgr::getGoalViewOffset_deg, &FGViewMgr::setGoalViewOffset_deg);
136   fgSetArchivable("/sim/current-view/goal-heading-offset-deg");
137   fgTie("/sim/current-view/pitch-offset-deg", this,
138         &FGViewMgr::getViewTilt_deg, &FGViewMgr::setViewTilt_deg);
139   fgSetArchivable("/sim/current-view/pitch-offset-deg");
140   fgTie("/sim/current-view/goal-pitch-offset-deg", this,
141         &FGViewMgr::getGoalViewTilt_deg, &FGViewMgr::setGoalViewTilt_deg);
142   fgSetArchivable("/sim/current-view/goal-pitch-offset-deg");
143
144   fgTie("/sim/current-view/axes/long", this,
145         (double_getter)0, &FGViewMgr::setViewAxisLong);
146   fgTie("/sim/current-view/axes/lat", this,
147         (double_getter)0, &FGViewMgr::setViewAxisLat);
148
149   fgTie("/sim/current-view/field-of-view", this,
150         &FGViewMgr::getFOV_deg, &FGViewMgr::setFOV_deg);
151   fgSetArchivable("/sim/current-view/field-of-view");
152
153   fgTie("/sim/current-view/ground-level-nearplane-m", this,
154         &FGViewMgr::getNear_m, &FGViewMgr::setNear_m);
155   fgSetArchivable("/sim/current-view/ground-level-nearplane-m");
156
157 }
158
159 void
160 FGViewMgr::unbind ()
161 {
162   // FIXME:
163   // need to redo these bindings to the new locations (move to viewer?)
164   fgUntie("/sim/current-view/heading-offset-deg");
165   fgUntie("/sim/current-view/goal-heading-offset-deg");
166   fgUntie("/sim/current-view/pitch-offset-deg");
167   fgUntie("/sim/current-view/goal-pitch-offset-deg");
168   fgUntie("/sim/field-of-view");
169   fgUntie("/sim/current-view/axes/long");
170   fgUntie("/sim/current-view/axes/lat");
171 }
172
173 void
174 FGViewMgr::update (double dt)
175 {
176   char stridx [20];
177   string viewpath, nodepath;
178   double lon_deg, lat_deg, alt_ft, roll_deg, pitch_deg, heading_deg;
179
180   FGViewer * view = get_current_view();
181   if (view == 0)
182     return;
183
184   // 
185   int i = current;
186   viewpath = "/sim/view";
187   sprintf(stridx, "[%d]", i);
188   viewpath += stridx;
189
190
191   FGViewer *loop_view = (FGViewer *)get_view( i );
192
193                 // Set up view location and orientation
194
195   nodepath = viewpath;
196   nodepath += "/config/from-model";
197   if (!fgGetBool(nodepath.c_str())) {
198     nodepath = viewpath;
199     nodepath += "/config/eye-lon-deg-path";
200     lon_deg = fgGetDouble(fgGetString(nodepath.c_str()));
201     nodepath = viewpath;
202     nodepath += "/config/eye-lat-deg-path";
203     lat_deg = fgGetDouble(fgGetString(nodepath.c_str()));
204     nodepath = viewpath;
205     nodepath += "/config/eye-alt-ft-path";
206     alt_ft = fgGetDouble(fgGetString(nodepath.c_str()));
207     nodepath = viewpath;
208     nodepath += "/config/eye-roll-deg-path";
209     roll_deg = fgGetDouble(fgGetString(nodepath.c_str()));
210     nodepath = viewpath;
211     nodepath += "/config/eye-pitch-deg-path";
212     pitch_deg = fgGetDouble(fgGetString(nodepath.c_str()));
213     nodepath = viewpath;
214     nodepath += "/config/eye-heading-deg-path";
215     heading_deg = fgGetDouble(fgGetString(nodepath.c_str()));
216     loop_view->setPosition(lon_deg, lat_deg, alt_ft);
217     loop_view->setOrientation(roll_deg, pitch_deg, heading_deg);
218   } else {
219     // force recalc in viewer
220     loop_view->set_dirty();
221   }
222
223   // if lookat (type 1) then get target data...
224   if (loop_view->getType() == FG_LOOKAT) {
225     nodepath = viewpath;
226     nodepath += "/config/from-model";
227     if (!fgGetBool(nodepath.c_str())) {
228       nodepath = viewpath;
229       nodepath += "/config/target-lon-deg-path";
230       lon_deg = fgGetDouble(fgGetString(nodepath.c_str()));
231       nodepath = viewpath;
232       nodepath += "/config/target-lat-deg-path";
233       lat_deg = fgGetDouble(fgGetString(nodepath.c_str()));
234       nodepath = viewpath;
235       nodepath += "/config/target-alt-ft-path";
236       alt_ft = fgGetDouble(fgGetString(nodepath.c_str()));
237       nodepath = viewpath;
238       nodepath += "/config/target-roll-deg-path";
239       roll_deg = fgGetDouble(fgGetString(nodepath.c_str()));
240       nodepath = viewpath;
241       nodepath += "/config/target-pitch-deg-path";
242       pitch_deg = fgGetDouble(fgGetString(nodepath.c_str()));
243       nodepath = viewpath;
244       nodepath += "/config/target-heading-deg-path";
245       heading_deg = fgGetDouble(fgGetString(nodepath.c_str()));
246      
247       loop_view ->setTargetPosition(lon_deg, lat_deg, alt_ft);
248       loop_view->setTargetOrientation(roll_deg, pitch_deg, heading_deg);
249     } else {
250       loop_view->set_dirty();
251     }
252   }
253   setPilotXOffset_m(fgGetDouble("/sim/current-view/x-offset-m"));
254   setPilotYOffset_m(fgGetDouble("/sim/current-view/y-offset-m"));
255   setPilotZOffset_m(fgGetDouble("/sim/current-view/z-offset-m"));
256
257                                 // Update the current view
258   do_axes();
259   view->update(dt);
260 }
261
262 void
263 FGViewMgr::copyToCurrent()
264 {
265     fgSetDouble("/sim/current-view/x-offset-m", getPilotXOffset_m());
266     fgSetDouble("/sim/current-view/y-offset-m", getPilotYOffset_m());
267     fgSetDouble("/sim/current-view/z-offset-m", getPilotZOffset_m());
268 }
269
270
271 double
272 FGViewMgr::getViewOffset_deg () const
273 {
274   const FGViewer * view = get_current_view();
275   return (view == 0 ? 0 : view->getHeadingOffset_deg());
276 }
277
278 void
279 FGViewMgr::setViewOffset_deg (double offset)
280 {
281   FGViewer * view = get_current_view();
282   if (view != 0) {
283     view->setGoalHeadingOffset_deg(offset);
284     view->setHeadingOffset_deg(offset);
285   }
286 }
287
288 double
289 FGViewMgr::getGoalViewOffset_deg () const
290 {
291   const FGViewer * view = get_current_view();
292   return (view == 0 ? 0 : view->getGoalHeadingOffset_deg());
293 }
294
295 void
296 FGViewMgr::setGoalViewOffset_deg (double offset)
297 {
298   FGViewer * view = get_current_view();
299   if (view != 0)
300     view->setGoalHeadingOffset_deg(offset);
301 }
302
303 double
304 FGViewMgr::getViewTilt_deg () const
305 {
306   const FGViewer * view = get_current_view();
307   return (view == 0 ? 0 : view->getPitchOffset_deg());
308 }
309
310 void
311 FGViewMgr::setViewTilt_deg (double tilt)
312 {
313   FGViewer * view = get_current_view();
314   if (view != 0) {
315     view->setGoalPitchOffset_deg(tilt);
316     view->setPitchOffset_deg(tilt);
317   }
318 }
319
320 double
321 FGViewMgr::getGoalViewTilt_deg () const
322 {
323   const FGViewer * view = get_current_view();
324   return (view == 0 ? 0 : view->getGoalPitchOffset_deg());
325 }
326
327 void
328 FGViewMgr::setGoalViewTilt_deg (double tilt)
329 {
330   FGViewer * view = get_current_view();
331   if (view != 0)
332     view->setGoalPitchOffset_deg(tilt);
333 }
334
335 double
336 FGViewMgr::getPilotXOffset_m () const
337 {
338   const FGViewer * view = get_current_view();
339   if (view != 0) {
340     return ((FGViewer *)view)->getXOffset_m();
341   } else {
342     return 0;
343   }
344 }
345
346 void
347 FGViewMgr::setPilotXOffset_m (double x)
348 {
349   FGViewer * view = get_current_view();
350   if (view != 0) {
351     view->setXOffset_m(x);
352   }
353 }
354
355 double
356 FGViewMgr::getPilotYOffset_m () const
357 {
358   const FGViewer * view = get_current_view();
359   if (view != 0) {
360     return ((FGViewer *)view)->getYOffset_m();
361   } else {
362     return 0;
363   }
364 }
365
366 void
367 FGViewMgr::setPilotYOffset_m (double y)
368 {
369   FGViewer * view = get_current_view();
370   if (view != 0) {
371     view->setYOffset_m(y);
372   }
373 }
374
375 double
376 FGViewMgr::getPilotZOffset_m () const
377 {
378   const FGViewer * view = get_current_view();
379   if (view != 0) {
380     return ((FGViewer *)view)->getZOffset_m();
381   } else {
382     return 0;
383   }
384 }
385
386 void
387 FGViewMgr::setPilotZOffset_m (double z)
388 {
389   FGViewer * view = get_current_view();
390   if (view != 0) {
391     view->setZOffset_m(z);
392   }
393 }
394
395 double
396 FGViewMgr::getFOV_deg () const
397 {
398   const FGViewer * view = get_current_view();
399   return (view == 0 ? 0 : view->get_fov());
400 }
401
402 void
403 FGViewMgr::setFOV_deg (double fov)
404 {
405   FGViewer * view = get_current_view();
406   if (view != 0)
407     view->set_fov(fov);
408 }
409
410 double
411 FGViewMgr::getNear_m () const
412 {
413   const FGViewer * view = get_current_view();
414   return (view == 0 ? 0.5f : view->getNear_m());
415 }
416
417 void
418 FGViewMgr::setNear_m (double near_m)
419 {
420   FGViewer * view = get_current_view();
421   if (view != 0)
422     view->setNear_m(near_m);
423 }
424
425 void
426 FGViewMgr::setViewAxisLong (double axis)
427 {
428   axis_long = axis;
429 }
430
431 void
432 FGViewMgr::setViewAxisLat (double axis)
433 {
434   axis_lat = axis;
435 }
436
437 void
438 FGViewMgr::do_axes ()
439 {
440                                 // Take no action when hat is centered
441   if ( ( axis_long <  0.01 ) &&
442        ( axis_long > -0.01 ) &&
443        ( axis_lat  <  0.01 ) &&
444        ( axis_lat  > -0.01 )
445      )
446     return;
447
448   double viewDir = 999;
449
450   /* Do all the quick and easy cases */
451   if (axis_long < 0) {          // Longitudinal axis forward
452     if (axis_lat == axis_long)
453       viewDir = 45;
454     else if (axis_lat == - axis_long)
455       viewDir = 315;
456     else if (axis_lat == 0)
457       viewDir = 0;
458   } else if (axis_long > 0) {   // Longitudinal axis backward
459     if (axis_lat == - axis_long)
460       viewDir = 135;
461     else if (axis_lat == axis_long)
462       viewDir = 225;
463     else if (axis_lat == 0)
464       viewDir = 180;
465   } else if (axis_long == 0) {  // Longitudinal axis neutral
466     if (axis_lat < 0)
467       viewDir = 90;
468     else if (axis_lat > 0)
469       viewDir = 270;
470     else return; /* And assertion failure maybe? */
471   }
472
473                                 // Do all the difficult cases
474   if ( viewDir > 900 )
475     viewDir = SGD_RADIANS_TO_DEGREES * atan2 ( -axis_lat, -axis_long );
476   if ( viewDir < -1 ) viewDir += 360;
477
478   get_current_view()->setGoalHeadingOffset_deg(viewDir);
479 }