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