1 // viewmgr.cxx -- class for managing all the views in the flightgear world.
3 // Written by Curtis Olson, started October 2000.
5 // Copyright (C) 2000 Curtis L. Olson - curt@flightgear.org
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.
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.
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.
25 #include <GUI/sgVec3Slider.hxx> // FIXME: this should NOT be needed
27 #include "viewmgr.hxx"
28 #include "fg_props.hxx"
32 FGViewMgr::FGViewMgr( void ) :
41 FGViewMgr::~FGViewMgr( void ) {
47 add_view(new FGViewerRPH);
48 add_view(new FGViewerLookAt);
51 typedef double (FGViewMgr::*double_getter)() const;
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);
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");
102 FGViewMgr::update (int dt)
104 FGViewer * view = get_current_view();
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")
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;
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 );
131 // Set up the chase view
133 // FIXME: the matrix math belongs in
134 // the viewer, not here.
135 FGViewerLookAt *chase_view = (FGViewerLookAt *)get_view( 1 );
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
143 chase_view->get_view_offset() * SGD_RADIANS_TO_DEGREES -
144 heading_rad * SGD_RADIANS_TO_DEGREES,
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 );
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 );
156 // Update the current view
162 FGViewMgr::getViewOffset_deg () const
164 const FGViewer * view = get_current_view();
165 return (view == 0 ? 0 : view->get_view_offset() * SGD_RADIANS_TO_DEGREES);
169 FGViewMgr::setViewOffset_deg (double offset)
171 FGViewer * view = get_current_view();
173 view->set_view_offset(offset * SGD_DEGREES_TO_RADIANS);
174 std::cout << "View offset is now " << offset << std::endl;
178 FGViewMgr::getGoalViewOffset_deg () const
180 const FGViewer * view = get_current_view();
181 return (view == 0 ? 0 : view->get_goal_view_offset() * SGD_RADIANS_TO_DEGREES);
185 FGViewMgr::setGoalViewOffset_deg (double offset)
187 FGViewer * view = get_current_view();
189 view->set_goal_view_offset(offset * SGD_DEGREES_TO_RADIANS);
190 std::cout << "Goal view offset is now " << offset << std::endl;
194 FGViewMgr::getViewTilt_deg () const
196 const FGViewer * view = get_current_view();
197 return (view == 0 ? 0 : view->get_view_tilt() * SGD_RADIANS_TO_DEGREES);
201 FGViewMgr::setViewTilt_deg (double tilt)
203 FGViewer * view = get_current_view();
205 view->set_view_tilt(tilt * SGD_DEGREES_TO_RADIANS);
209 FGViewMgr::getGoalViewTilt_deg () const
211 const FGViewer * view = get_current_view();
212 return (view == 0 ? 0 : view->get_goal_view_tilt() * SGD_RADIANS_TO_DEGREES);
216 FGViewMgr::setGoalViewTilt_deg (double tilt)
218 FGViewer * view = get_current_view();
220 view->set_goal_view_tilt(tilt * SGD_DEGREES_TO_RADIANS);
224 FGViewMgr::getPilotXOffset_m () const
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();
237 FGViewMgr::setPilotXOffset_m (double x)
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]);
248 FGViewMgr::getPilotYOffset_m () const
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();
261 FGViewMgr::setPilotYOffset_m (double y)
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]);
272 FGViewMgr::getPilotZOffset_m () const
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();
285 FGViewMgr::setPilotZOffset_m (double z)
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);
296 FGViewMgr::getFOV_deg () const
298 const FGViewer * view = get_current_view();
299 return (view == 0 ? 0 : view->get_fov());
303 FGViewMgr::setFOV_deg (double fov)
305 FGViewer * view = get_current_view();
311 FGViewMgr::setViewAxisLong (double axis)
317 FGViewMgr::setViewAxisLat (double axis)
323 FGViewMgr::do_axes ()
325 // Take no action when hat is centered
326 if ( ( axis_long < 0.01 ) &&
327 ( axis_long > -0.01 ) &&
328 ( axis_lat < 0.01 ) &&
333 double viewDir = 999;
335 /* Do all the quick and easy cases */
336 if (axis_long < 0) { // Longitudinal axis forward
337 if (axis_lat == axis_long)
339 else if (axis_lat == - axis_long)
341 else if (axis_lat == 0)
343 } else if (axis_long > 0) { // Longitudinal axis backward
344 if (axis_lat == - axis_long)
346 else if (axis_lat == axis_long)
348 else if (axis_lat == 0)
350 } else if (axis_long == 0) { // Longitudinal axis neutral
353 else if (axis_lat > 0)
355 else return; /* And assertion failure maybe? */
358 // Do all the difficult cases
360 viewDir = SGD_RADIANS_TO_DEGREES * atan2 ( -axis_lat, -axis_long );
361 if ( viewDir < -1 ) viewDir += 360;
363 get_current_view()->set_goal_view_offset(viewDir*SGD_DEGREES_TO_RADIANS);