]> git.mxchange.org Git - flightgear.git/blob - src/Main/viewmgr.cxx
Small tweak to make the Irix compiler happy.
[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 <GUI/sgVec3Slider.hxx> // FIXME: this should NOT be needed
29
30 #include "viewmgr.hxx"
31 #include "fg_props.hxx"
32
33 // strings 
34 string viewpath, nodepath, strdata;
35
36 // Constructor
37 FGViewMgr::FGViewMgr( void ) :
38   axis_long(0),
39   axis_lat(0),
40   current(0)
41 {
42 }
43
44
45 // Destructor
46 FGViewMgr::~FGViewMgr( void ) {
47 }
48
49 void
50 FGViewMgr::init ()
51 {
52   char stridx [ 20 ];
53   bool from_model = false;
54   bool at_model = false;
55   int from_model_index = 0;
56   int at_model_index = 0;
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     // supporting two types now "lookat" = 1 and "lookfrom" = 0
98     if ( strcmp("lookat",strdata.c_str()) == 0 )
99       add_view(new FGViewer ( FG_LOOKAT, from_model, from_model_index, at_model, at_model_index ));
100     else
101       add_view(new FGViewer ( FG_LOOKFROM, from_model, from_model_index, false, 0 ));
102   }
103 }
104
105 typedef double (FGViewMgr::*double_getter)() const;
106
107 void
108 FGViewMgr::bind ()
109 {
110   // FIXME:
111   // need to redo these bindings to the new locations (move to viewer?)
112   fgTie("/sim/view/offset-deg", this,
113         &FGViewMgr::getViewOffset_deg, &FGViewMgr::setViewOffset_deg);
114   fgSetArchivable("/sim/view/offset-deg");
115   fgTie("/sim/view/goal-offset-deg", this,
116         &FGViewMgr::getGoalViewOffset_deg, &FGViewMgr::setGoalViewOffset_deg);
117   fgSetArchivable("/sim/view/goal-offset-deg");
118   fgTie("/sim/view/tilt-deg", this,
119         &FGViewMgr::getViewTilt_deg, &FGViewMgr::setViewTilt_deg);
120   fgSetArchivable("/sim/view/tilt-deg");
121   fgTie("/sim/view/goal-tilt-deg", this,
122         &FGViewMgr::getGoalViewTilt_deg, &FGViewMgr::setGoalViewTilt_deg);
123   fgSetArchivable("/sim/view/goal-tilt-deg");
124   fgTie("/sim/view/pilot/x-offset-m", this,
125         &FGViewMgr::getPilotXOffset_m, &FGViewMgr::setPilotXOffset_m);
126   fgSetArchivable("/sim/view/pilot/x-offset-m");
127   fgTie("/sim/view/pilot/y-offset-m", this,
128         &FGViewMgr::getPilotYOffset_m, &FGViewMgr::setPilotYOffset_m);
129   fgSetArchivable("/sim/view/pilot/y-offset-m");
130   fgTie("/sim/view/pilot/z-offset-m", this,
131         &FGViewMgr::getPilotZOffset_m, &FGViewMgr::setPilotZOffset_m);
132   fgSetArchivable("/sim/view/pilot/z-offset-m");
133   fgTie("/sim/field-of-view", this,
134         &FGViewMgr::getFOV_deg, &FGViewMgr::setFOV_deg);
135   fgSetArchivable("/sim/field-of-view");
136   fgTie("/sim/view/axes/long", this,
137         (double_getter)0, &FGViewMgr::setViewAxisLong);
138   fgTie("/sim/view/axes/lat", this,
139         (double_getter)0, &FGViewMgr::setViewAxisLat);
140 }
141
142 void
143 FGViewMgr::unbind ()
144 {
145   // FIXME:
146   // need to redo these bindings to the new locations (move to viewer?)
147   fgUntie("/sim/view/offset-deg");
148   fgUntie("/sim/view/goal-offset-deg");
149   fgUntie("/sim/view/tilt-deg");
150   fgUntie("/sim/view/goal-tilt-deg");
151   fgUntie("/sim/view/pilot/x-offset-m");
152   fgUntie("/sim/view/pilot/y-offset-m");
153   fgUntie("/sim/view/pilot/z-offset-m");
154   fgUntie("/sim/field-of-view");
155   fgUntie("/sim/view/axes/long");
156   fgUntie("/sim/view/axes/lat");
157 }
158
159 void
160 FGViewMgr::update (int dt)
161 {
162   char stridx [20];
163   double lon_deg, lat_deg, alt_ft, roll_deg, pitch_deg, heading_deg;
164
165   FGViewer * view = get_current_view();
166   if (view == 0)
167     return;
168
169   // 
170   int i = current;
171   viewpath = "/sim/view";
172   sprintf(stridx, "[%d]", i);
173   viewpath += stridx;
174
175
176   FGViewer *loop_view = (FGViewer *)get_view( i );
177
178                 // Set up view location and orientation
179
180   nodepath = viewpath;
181   nodepath += "/config/from-model";
182   if (!fgGetBool(nodepath.c_str())) {
183     nodepath = viewpath;
184     nodepath += "/config/eye-lon-deg-path";
185     lon_deg = fgGetDouble(fgGetString(nodepath.c_str()));
186     nodepath = viewpath;
187     nodepath += "/config/eye-lat-deg-path";
188     lat_deg = fgGetDouble(fgGetString(nodepath.c_str()));
189     nodepath = viewpath;
190     nodepath += "/config/eye-alt-ft-path";
191     alt_ft = fgGetDouble(fgGetString(nodepath.c_str()));
192     nodepath = viewpath;
193     nodepath += "/config/eye-roll-deg-path";
194     roll_deg = fgGetDouble(fgGetString(nodepath.c_str()));
195     nodepath = viewpath;
196     nodepath += "/config/eye-pitch-deg-path";
197     pitch_deg = fgGetDouble(fgGetString(nodepath.c_str()));
198     nodepath = viewpath;
199     nodepath += "/config/eye-heading-deg-path";
200     heading_deg = fgGetDouble(fgGetString(nodepath.c_str()));
201     loop_view->setPosition(lon_deg, lat_deg, alt_ft);
202     loop_view->setOrientation(roll_deg, pitch_deg, heading_deg);
203   } else {
204     // force recalc in viewer
205     loop_view->set_dirty();
206   }
207
208   // if lookat (type 1) then get target data...
209   if (loop_view->getType() == 1) {
210     nodepath = viewpath;
211     nodepath += "/config/from-model";
212     if (!fgGetBool(nodepath.c_str())) {
213       nodepath = viewpath;
214       nodepath += "/config/target-lon-deg-path";
215       lon_deg = fgGetDouble(fgGetString(nodepath.c_str()));
216       nodepath = viewpath;
217       nodepath += "/config/target-lat-deg-path";
218       lat_deg = fgGetDouble(fgGetString(nodepath.c_str()));
219       nodepath = viewpath;
220       nodepath += "/config/target-alt-ft-path";
221       alt_ft = fgGetDouble(fgGetString(nodepath.c_str()));
222       nodepath = viewpath;
223       nodepath += "/config/target-roll-deg-path";
224       roll_deg = fgGetDouble(fgGetString(nodepath.c_str()));
225       nodepath = viewpath;
226       nodepath += "/config/target-pitch-deg-path";
227       pitch_deg = fgGetDouble(fgGetString(nodepath.c_str()));
228       nodepath = viewpath;
229       nodepath += "/config/target-heading-deg-path";
230       heading_deg = fgGetDouble(fgGetString(nodepath.c_str()));
231      
232       loop_view ->setTargetPosition(lon_deg, lat_deg, alt_ft);
233       loop_view->setTargetOrientation(roll_deg, pitch_deg, heading_deg);
234     } else {
235       loop_view->set_dirty();
236     }
237   }
238
239                                 // Set up the chase view
240   // FIXME:
241   // Gotta change sgVec3Slider so that it takes xyz values as inputs 
242   // instead of spherical coordinates.
243   FGViewer *chase_view = (FGViewer *)get_view( 1 );
244
245   // get xyz Position offsets directly from GUI/sgVec3Slider
246   // FIXME: change GUI/sgVec3Slider to store the xyz in properties
247   // it would probably be faster than the way PilotOffsetGet()
248   // triggers a recalc all the time.
249   sgVec3 *pPO = PilotOffsetGet();
250   sgVec3 zPO;
251   sgCopyVec3( zPO, *pPO );
252   chase_view->setPositionOffsets(zPO[1], zPO[2], zPO[0] );
253
254                                 // Update the current view
255   do_axes();
256   view->update(dt);
257 }
258
259 double
260 FGViewMgr::getViewOffset_deg () const
261 {
262   const FGViewer * view = get_current_view();
263   return (view == 0 ? 0 : view->getHeadingOffset_deg());
264 }
265
266 void
267 FGViewMgr::setViewOffset_deg (double offset)
268 {
269   FGViewer * view = get_current_view();
270   if (view != 0) {
271     view->setGoalHeadingOffset_deg(offset);
272     view->setHeadingOffset_deg(offset);
273   }
274 }
275
276 double
277 FGViewMgr::getGoalViewOffset_deg () const
278 {
279   const FGViewer * view = get_current_view();
280   return (view == 0 ? 0 : view->getGoalHeadingOffset_deg());
281 }
282
283 void
284 FGViewMgr::setGoalViewOffset_deg (double offset)
285 {
286   FGViewer * view = get_current_view();
287   if (view != 0)
288     view->setGoalHeadingOffset_deg(offset);
289 }
290
291 double
292 FGViewMgr::getViewTilt_deg () const
293 {
294   const FGViewer * view = get_current_view();
295   return (view == 0 ? 0 : view->getPitchOffset_deg());
296 }
297
298 void
299 FGViewMgr::setViewTilt_deg (double tilt)
300 {
301   FGViewer * view = get_current_view();
302   if (view != 0) {
303     view->setGoalPitchOffset_deg(tilt);
304     view->setPitchOffset_deg(tilt);
305   }
306 }
307
308 double
309 FGViewMgr::getGoalViewTilt_deg () const
310 {
311   const FGViewer * view = get_current_view();
312   return (view == 0 ? 0 : view->getGoalPitchOffset_deg());
313 }
314
315 void
316 FGViewMgr::setGoalViewTilt_deg (double tilt)
317 {
318   FGViewer * view = get_current_view();
319   if (view != 0)
320     view->setGoalPitchOffset_deg(tilt);
321 }
322
323 double
324 FGViewMgr::getPilotXOffset_m () const
325 {
326                                 // FIXME: hard-coded pilot view position
327   const FGViewer * pilot_view = get_view(0);
328   if (pilot_view != 0) {
329     return ((FGViewer *)pilot_view)->getXOffset_m();
330   } else {
331     return 0;
332   }
333 }
334
335 void
336 FGViewMgr::setPilotXOffset_m (double x)
337 {
338                                 // FIXME: hard-coded pilot view position
339   FGViewer * pilot_view = get_view(0);
340   if (pilot_view != 0) {
341     pilot_view->setXOffset_m(x);
342   }
343 }
344
345 double
346 FGViewMgr::getPilotYOffset_m () const
347 {
348                                 // FIXME: hard-coded pilot view position
349   const FGViewer * pilot_view = get_view(0);
350   if (pilot_view != 0) {
351     return ((FGViewer *)pilot_view)->getYOffset_m();
352   } else {
353     return 0;
354   }
355 }
356
357 void
358 FGViewMgr::setPilotYOffset_m (double y)
359 {
360                                 // FIXME: hard-coded pilot view position
361   FGViewer * pilot_view = get_view(0);
362   if (pilot_view != 0) {
363     pilot_view->setYOffset_m(y);
364   }
365 }
366
367 double
368 FGViewMgr::getPilotZOffset_m () const
369 {
370                                 // FIXME: hard-coded pilot view position
371   const FGViewer * pilot_view = get_view(0);
372   if (pilot_view != 0) {
373     return ((FGViewer *)pilot_view)->getZOffset_m();
374   } else {
375     return 0;
376   }
377 }
378
379 void
380 FGViewMgr::setPilotZOffset_m (double z)
381 {
382                                 // FIXME: hard-coded pilot view position
383   FGViewer * pilot_view = get_view(0);
384   if (pilot_view != 0) {
385     pilot_view->setZOffset_m(z);
386   }
387 }
388
389 double
390 FGViewMgr::getFOV_deg () const
391 {
392   const FGViewer * view = get_current_view();
393   return (view == 0 ? 0 : view->get_fov());
394 }
395
396 void
397 FGViewMgr::setFOV_deg (double fov)
398 {
399   FGViewer * view = get_current_view();
400   if (view != 0)
401     view->set_fov(fov);
402 }
403
404 void
405 FGViewMgr::setViewAxisLong (double axis)
406 {
407   axis_long = axis;
408 }
409
410 void
411 FGViewMgr::setViewAxisLat (double axis)
412 {
413   axis_lat = axis;
414 }
415
416 void
417 FGViewMgr::do_axes ()
418 {
419                                 // Take no action when hat is centered
420   if ( ( axis_long <  0.01 ) &&
421        ( axis_long > -0.01 ) &&
422        ( axis_lat  <  0.01 ) &&
423        ( axis_lat  > -0.01 )
424      )
425     return;
426
427   double viewDir = 999;
428
429   /* Do all the quick and easy cases */
430   if (axis_long < 0) {          // Longitudinal axis forward
431     if (axis_lat == axis_long)
432       viewDir = 45;
433     else if (axis_lat == - axis_long)
434       viewDir = 315;
435     else if (axis_lat == 0)
436       viewDir = 0;
437   } else if (axis_long > 0) {   // Longitudinal axis backward
438     if (axis_lat == - axis_long)
439       viewDir = 135;
440     else if (axis_lat == axis_long)
441       viewDir = 225;
442     else if (axis_lat == 0)
443       viewDir = 180;
444   } else if (axis_long == 0) {  // Longitudinal axis neutral
445     if (axis_lat < 0)
446       viewDir = 90;
447     else if (axis_lat > 0)
448       viewDir = 270;
449     else return; /* And assertion failure maybe? */
450   }
451
452                                 // Do all the difficult cases
453   if ( viewDir > 900 )
454     viewDir = SGD_RADIANS_TO_DEGREES * atan2 ( -axis_lat, -axis_long );
455   if ( viewDir < -1 ) viewDir += 360;
456
457   get_current_view()->setGoalHeadingOffset_deg(viewDir);
458 }
459