]> git.mxchange.org Git - flightgear.git/blob - src/Main/viewmgr.cxx
2d8b3f7ebe17a06ee16fd4ce42da82bb01b5aaa2
[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   for (int i = 0; i < fgGetInt("/sim/number-views"); i++) {
54     nodepath = "/sim/view";
55     sprintf(stridx, "[%d]", i);
56     nodepath += stridx;
57     nodepath += "/type";
58     strdata = fgGetString(nodepath.c_str());
59     // supporting two types now "lookat" = 1 and "lookfrom" = 1
60     if ( strcmp("lookat",strdata.c_str()) == 0 )
61       add_view(new FGViewer, 1);
62     else
63       add_view(new FGViewer, 0);
64   }
65 }
66
67 typedef double (FGViewMgr::*double_getter)() const;
68
69 void
70 FGViewMgr::bind ()
71 {
72   // FIXME:
73   // need to redo these bindings to the new locations (move to viewer?)
74   fgTie("/sim/view/offset-deg", this,
75         &FGViewMgr::getViewOffset_deg, &FGViewMgr::setViewOffset_deg);
76   fgSetArchivable("/sim/view/offset-deg");
77   fgTie("/sim/view/goal-offset-deg", this,
78         &FGViewMgr::getGoalViewOffset_deg, &FGViewMgr::setGoalViewOffset_deg);
79   fgSetArchivable("/sim/view/goal-offset-deg");
80   fgTie("/sim/view/tilt-deg", this,
81         &FGViewMgr::getViewTilt_deg, &FGViewMgr::setViewTilt_deg);
82   fgSetArchivable("/sim/view/tilt-deg");
83   fgTie("/sim/view/goal-tilt-deg", this,
84         &FGViewMgr::getGoalViewTilt_deg, &FGViewMgr::setGoalViewTilt_deg);
85   fgSetArchivable("/sim/view/goal-tilt-deg");
86   fgTie("/sim/view/pilot/x-offset-m", this,
87         &FGViewMgr::getPilotXOffset_m, &FGViewMgr::setPilotXOffset_m);
88   fgSetArchivable("/sim/view/pilot/x-offset-m");
89   fgTie("/sim/view/pilot/y-offset-m", this,
90         &FGViewMgr::getPilotYOffset_m, &FGViewMgr::setPilotYOffset_m);
91   fgSetArchivable("/sim/view/pilot/y-offset-m");
92   fgTie("/sim/view/pilot/z-offset-m", this,
93         &FGViewMgr::getPilotZOffset_m, &FGViewMgr::setPilotZOffset_m);
94   fgSetArchivable("/sim/view/pilot/z-offset-m");
95   fgTie("/sim/field-of-view", this,
96         &FGViewMgr::getFOV_deg, &FGViewMgr::setFOV_deg);
97   fgSetArchivable("/sim/field-of-view");
98   fgTie("/sim/view/axes/long", this,
99         (double_getter)0, &FGViewMgr::setViewAxisLong);
100   fgTie("/sim/view/axes/lat", this,
101         (double_getter)0, &FGViewMgr::setViewAxisLat);
102 }
103
104 void
105 FGViewMgr::unbind ()
106 {
107   // FIXME:
108   // need to redo these bindings to the new locations (move to viewer?)
109   fgUntie("/sim/view/offset-deg");
110   fgUntie("/sim/view/goal-offset-deg");
111   fgUntie("/sim/view/tilt-deg");
112   fgUntie("/sim/view/goal-tilt-deg");
113   fgUntie("/sim/view/pilot/x-offset-m");
114   fgUntie("/sim/view/pilot/y-offset-m");
115   fgUntie("/sim/view/pilot/z-offset-m");
116   fgUntie("/sim/field-of-view");
117   fgUntie("/sim/view/axes/long");
118   fgUntie("/sim/view/axes/lat");
119 }
120
121 void
122 FGViewMgr::update (int dt)
123 {
124   char stridx [20];
125
126   FGViewer * view = get_current_view();
127   if (view == 0)
128     return;
129
130   for (int i = 0; i < fgGetInt("/sim/number-views"); i++) {
131     viewpath = "/sim/view";
132     sprintf(stridx, "[%d]", i);
133     viewpath += stridx;
134
135
136     FGViewer *loop_view = (FGViewer *)get_view( i );
137
138                 // Set up view
139     nodepath = viewpath;
140     nodepath += "/config/eye-lon-deg-path";
141     double lon_deg = fgGetDouble(fgGetString(nodepath.c_str()));
142     nodepath = viewpath;
143     nodepath += "/config/eye-lat-deg-path";
144     double lat_deg = fgGetDouble(fgGetString(nodepath.c_str()));
145     nodepath = viewpath;
146     nodepath += "/config/eye-alt-ft-path";
147     double alt_ft = fgGetDouble(fgGetString(nodepath.c_str()));
148     nodepath = viewpath;
149     nodepath += "/config/eye-roll-deg-path";
150     double roll_deg = fgGetDouble(fgGetString(nodepath.c_str()));
151     nodepath = viewpath;
152     nodepath += "/config/eye-pitch-deg-path";
153     double pitch_deg = fgGetDouble(fgGetString(nodepath.c_str()));
154     nodepath = viewpath;
155     nodepath += "/config/eye-heading-deg-path";
156     double heading_deg = fgGetDouble(fgGetString(nodepath.c_str()));
157   
158     loop_view->setPosition(lon_deg, lat_deg, alt_ft);
159     loop_view->setOrientation(roll_deg, pitch_deg, heading_deg);
160
161     // if lookat (type 1) then get target data...
162     if (loop_view->getType() == 1) {
163       nodepath = viewpath;
164       nodepath += "/config/target-lon-deg-path";
165       lon_deg = fgGetDouble(fgGetString(nodepath.c_str()));
166       nodepath = viewpath;
167       nodepath += "/config/target-lat-deg-path";
168       lat_deg = fgGetDouble(fgGetString(nodepath.c_str()));
169       nodepath = viewpath;
170       nodepath += "/config/target-alt-ft-path";
171       alt_ft = fgGetDouble(fgGetString(nodepath.c_str()));
172       nodepath = viewpath;
173       nodepath += "/config/target-roll-deg-path";
174       roll_deg = fgGetDouble(fgGetString(nodepath.c_str()));
175       nodepath = viewpath;
176       nodepath += "/config/target-pitch-deg-path";
177       pitch_deg = fgGetDouble(fgGetString(nodepath.c_str()));
178       nodepath = viewpath;
179       nodepath += "/config/target-heading-deg-path";
180       heading_deg = fgGetDouble(fgGetString(nodepath.c_str()));
181     
182       loop_view ->setTargetPosition(lon_deg, lat_deg, alt_ft);
183       loop_view->setTargetOrientation(roll_deg, pitch_deg, heading_deg);
184     }
185   }
186
187                                 // Set up the chase view
188   // FIXME:
189   // Gotta change sgVec3Slider so that it takes xyz values as inputs 
190   // instead of spherical coordinates.
191   FGViewer *chase_view = (FGViewer *)get_view( 1 );
192
193   // get xyz Position offsets directly from GUI/sgVec3Slider
194   // FIXME: change GUI/sgVec3Slider to store the xyz in properties
195   // it would probably be faster than the way PilotOffsetGet()
196   // triggers a recalc all the time.
197   sgVec3 *pPO = PilotOffsetGet();
198   sgVec3 zPO;
199   sgCopyVec3( zPO, *pPO );
200   chase_view->setPositionOffsets(zPO[1], zPO[0], zPO[2] );
201
202                                 // Update the current view
203   do_axes();
204   view->update(dt);
205 }
206
207 double
208 FGViewMgr::getViewOffset_deg () const
209 {
210   const FGViewer * view = get_current_view();
211   return (view == 0 ? 0 : view->getHeadingOffset_deg());
212 }
213
214 void
215 FGViewMgr::setViewOffset_deg (double offset)
216 {
217   FGViewer * view = get_current_view();
218   if (view != 0) {
219     view->setGoalHeadingOffset_deg(offset);
220     view->setHeadingOffset_deg(offset);
221   }
222 }
223
224 double
225 FGViewMgr::getGoalViewOffset_deg () const
226 {
227   const FGViewer * view = get_current_view();
228   return (view == 0 ? 0 : view->getGoalHeadingOffset_deg());
229 }
230
231 void
232 FGViewMgr::setGoalViewOffset_deg (double offset)
233 {
234   FGViewer * view = get_current_view();
235   if (view != 0)
236     view->setGoalHeadingOffset_deg(offset);
237 }
238
239 double
240 FGViewMgr::getViewTilt_deg () const
241 {
242   const FGViewer * view = get_current_view();
243   return (view == 0 ? 0 : view->getPitchOffset_deg());
244 }
245
246 void
247 FGViewMgr::setViewTilt_deg (double tilt)
248 {
249   FGViewer * view = get_current_view();
250   if (view != 0) {
251     view->setGoalPitchOffset_deg(tilt);
252     view->setPitchOffset_deg(tilt);
253   }
254 }
255
256 double
257 FGViewMgr::getGoalViewTilt_deg () const
258 {
259   const FGViewer * view = get_current_view();
260   return (view == 0 ? 0 : view->getGoalPitchOffset_deg());
261 }
262
263 void
264 FGViewMgr::setGoalViewTilt_deg (double tilt)
265 {
266   FGViewer * view = get_current_view();
267   if (view != 0)
268     view->setGoalPitchOffset_deg(tilt);
269 }
270
271 double
272 FGViewMgr::getPilotXOffset_m () const
273 {
274                                 // FIXME: hard-coded pilot view position
275   const FGViewer * pilot_view = get_view(0);
276   if (pilot_view != 0) {
277     return ((FGViewer *)pilot_view)->getXOffset_m();
278   } else {
279     return 0;
280   }
281 }
282
283 void
284 FGViewMgr::setPilotXOffset_m (double x)
285 {
286                                 // FIXME: hard-coded pilot view position
287   FGViewer * pilot_view = get_view(0);
288   if (pilot_view != 0) {
289     pilot_view->setXOffset_m(x);
290   }
291 }
292
293 double
294 FGViewMgr::getPilotYOffset_m () const
295 {
296                                 // FIXME: hard-coded pilot view position
297   const FGViewer * pilot_view = get_view(0);
298   if (pilot_view != 0) {
299     return ((FGViewer *)pilot_view)->getYOffset_m();
300   } else {
301     return 0;
302   }
303 }
304
305 void
306 FGViewMgr::setPilotYOffset_m (double y)
307 {
308                                 // FIXME: hard-coded pilot view position
309   FGViewer * pilot_view = get_view(0);
310   if (pilot_view != 0) {
311     pilot_view->setYOffset_m(y);
312   }
313 }
314
315 double
316 FGViewMgr::getPilotZOffset_m () const
317 {
318                                 // FIXME: hard-coded pilot view position
319   const FGViewer * pilot_view = get_view(0);
320   if (pilot_view != 0) {
321     return ((FGViewer *)pilot_view)->getZOffset_m();
322   } else {
323     return 0;
324   }
325 }
326
327 void
328 FGViewMgr::setPilotZOffset_m (double z)
329 {
330                                 // FIXME: hard-coded pilot view position
331   FGViewer * pilot_view = get_view(0);
332   if (pilot_view != 0) {
333     pilot_view->setZOffset_m(z);
334   }
335 }
336
337 double
338 FGViewMgr::getFOV_deg () const
339 {
340   const FGViewer * view = get_current_view();
341   return (view == 0 ? 0 : view->get_fov());
342 }
343
344 void
345 FGViewMgr::setFOV_deg (double fov)
346 {
347   FGViewer * view = get_current_view();
348   if (view != 0)
349     view->set_fov(fov);
350 }
351
352 void
353 FGViewMgr::setViewAxisLong (double axis)
354 {
355   axis_long = axis;
356 }
357
358 void
359 FGViewMgr::setViewAxisLat (double axis)
360 {
361   axis_lat = axis;
362 }
363
364 void
365 FGViewMgr::do_axes ()
366 {
367                                 // Take no action when hat is centered
368   if ( ( axis_long <  0.01 ) &&
369        ( axis_long > -0.01 ) &&
370        ( axis_lat  <  0.01 ) &&
371        ( axis_lat  > -0.01 )
372      )
373     return;
374
375   double viewDir = 999;
376
377   /* Do all the quick and easy cases */
378   if (axis_long < 0) {          // Longitudinal axis forward
379     if (axis_lat == axis_long)
380       viewDir = 45;
381     else if (axis_lat == - axis_long)
382       viewDir = 315;
383     else if (axis_lat == 0)
384       viewDir = 0;
385   } else if (axis_long > 0) {   // Longitudinal axis backward
386     if (axis_lat == - axis_long)
387       viewDir = 135;
388     else if (axis_lat == axis_long)
389       viewDir = 225;
390     else if (axis_lat == 0)
391       viewDir = 180;
392   } else if (axis_long == 0) {  // Longitudinal axis neutral
393     if (axis_lat < 0)
394       viewDir = 90;
395     else if (axis_lat > 0)
396       viewDir = 270;
397     else return; /* And assertion failure maybe? */
398   }
399
400                                 // Do all the difficult cases
401   if ( viewDir > 900 )
402     viewDir = SGD_RADIANS_TO_DEGREES * atan2 ( -axis_lat, -axis_long );
403   if ( viewDir < -1 ) viewDir += 360;
404
405   get_current_view()->setGoalHeadingOffset_deg(viewDir);
406 }
407