1 // views.cxx -- data structures and routines for managing and view
4 // Written by Curtis Olson, started August 1997.
6 // Copyright (C) 1997 Curtis L. Olson - curt@infoplane.com
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.
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.
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.
29 #include <ssg.h> // plib include
31 #include <Aircraft/aircraft.hxx>
32 #include <Cockpit/panel.hxx>
33 #include <Debug/logstream.hxx>
34 #include <Include/fg_constants.h>
35 #include <Math/mat3.h>
36 #include <Math/point3d.hxx>
37 #include <Math/polar3d.hxx>
38 #include <Math/vector.hxx>
39 #include <Scenery/scenery.hxx>
40 #include <Time/fg_time.hxx>
42 #include "options.hxx"
46 // temporary (hopefully) hack
47 static int panel_hist = 0;
50 // This is a record containing current view parameters for the current
54 // This is a record containing current view parameters for the current
60 FGView::FGView( void ) {
64 // Initialize a view structure
65 void FGView::Init( void ) {
66 FG_LOG( FG_VIEW, FG_INFO, "Initializing View parameters" );
69 goal_view_offset = 0.0;
71 winWidth = current_options.get_xsize();
72 winHeight = current_options.get_ysize();
74 if ( ! current_options.get_panel_status() ) {
75 current_view.set_win_ratio( (GLfloat) winWidth / (GLfloat) winHeight );
77 current_view.set_win_ratio( (GLfloat) winWidth /
78 ((GLfloat) (winHeight)*0.4232) );
81 // This never changes -- NHV
82 sgLARC_TO_SSG[0][0] = 0.0;
83 sgLARC_TO_SSG[0][1] = 1.0;
84 sgLARC_TO_SSG[0][2] = -0.0;
85 sgLARC_TO_SSG[0][3] = 0.0;
87 sgLARC_TO_SSG[1][0] = 0.0;
88 sgLARC_TO_SSG[1][1] = 0.0;
89 sgLARC_TO_SSG[1][2] = 1.0;
90 sgLARC_TO_SSG[1][3] = 0.0;
92 sgLARC_TO_SSG[2][0] = 1.0;
93 sgLARC_TO_SSG[2][1] = -0.0;
94 sgLARC_TO_SSG[2][2] = 0.0;
95 sgLARC_TO_SSG[2][3] = 0.0;
97 sgLARC_TO_SSG[3][0] = 0.0;
98 sgLARC_TO_SSG[3][1] = 0.0;
99 sgLARC_TO_SSG[3][2] = 0.0;
100 sgLARC_TO_SSG[3][3] = 1.0;
102 force_update_fov_math();
105 // Update the view volume, position, and orientation
106 void FGView::UpdateViewParams( const FGInterface& f ) {
109 if ((current_options.get_panel_status() != panel_hist) && (current_options.get_panel_status()))
111 FGPanel::OurPanel->ReInit( 0, 0, 1024, 768);
114 if ( ! current_options.get_panel_status() ) {
115 xglViewport(0, 0 , (GLint)(winWidth), (GLint)(winHeight) );
117 xglViewport(0, (GLint)((winHeight)*0.5768), (GLint)(winWidth),
118 (GLint)((winHeight)*0.4232) );
121 panel_hist = current_options.get_panel_status();
125 // convert sgMat4 to MAT3 and print
126 static void print_sgMat4( sgMat4 &in) {
130 for ( i = 0; i < 4; i++ ) {
131 for ( j = 0; j < 4; j++ ) {
132 print[i][j] = in[i][j];
135 MAT3print( print, stdout);
139 // convert convert MAT3 to sgMat4
140 static void MAT3mat_To_sgMat4( MAT3mat &in, sgMat4 &out ) {
141 out[0][0] = in[0][0];
142 out[0][1] = in[0][1];
143 out[0][2] = in[0][2];
144 out[0][3] = in[0][3];
145 out[1][0] = in[1][0];
146 out[1][1] = in[1][1];
147 out[1][2] = in[1][2];
148 out[1][3] = in[1][3];
149 out[2][0] = in[2][0];
150 out[2][1] = in[2][1];
151 out[2][2] = in[2][2];
152 out[2][3] = in[2][3];
153 out[3][0] = in[3][0];
154 out[3][1] = in[3][1];
155 out[3][2] = in[3][2];
156 out[3][3] = in[3][3];
160 // Update the view parameters
161 void FGView::UpdateViewMath( const FGInterface& f ) {
163 MAT3vec vec, forward, v0, minus_z;
164 MAT3mat R, TMP, UP, LOCAL, VIEW;
168 ssgSetFOV( current_options.get_fov(),
169 current_options.get_fov() * win_ratio );
173 scenery.center = scenery.next_center;
175 // printf("scenery center = %.2f %.2f %.2f\n", scenery.center.x,
176 // scenery.center.y, scenery.center.z);
178 // calculate the cartesion coords of the current lat/lon/0 elev
179 p = Point3D( f.get_Longitude(),
180 f.get_Lat_geocentric(),
181 f.get_Sea_level_radius() * FEET_TO_METER );
183 cur_zero_elev = fgPolarToCart3d(p) - scenery.center;
185 // calculate view position in current FG view coordinate system
186 // p.lon & p.lat are already defined earlier, p.radius was set to
187 // the sea level radius, so now we add in our altitude.
188 if ( f.get_Altitude() * FEET_TO_METER >
189 (scenery.cur_elev + 0.5 * METER_TO_FEET) ) {
190 p.setz( p.radius() + f.get_Altitude() * FEET_TO_METER );
192 p.setz( p.radius() + scenery.cur_elev + 0.5 * METER_TO_FEET );
195 abs_view_pos = fgPolarToCart3d(p);
197 view_pos = abs_view_pos - scenery.center;
199 FG_LOG( FG_VIEW, FG_DEBUG, "Polar view pos = " << p );
200 FG_LOG( FG_VIEW, FG_DEBUG, "Absolute view pos = " << abs_view_pos );
201 FG_LOG( FG_VIEW, FG_DEBUG, "Relative view pos = " << view_pos );
203 // code to calculate LOCAL matrix calculated from Phi, Theta, and
204 // Psi (roll, pitch, yaw) in case we aren't running LaRCsim as our
207 MAT3_SET_VEC(vec, 0.0, 0.0, 1.0);
208 MAT3rotate(R, vec, f.get_Phi());
209 // cout << "Roll matrix" << endl;
210 // MAT3print(R, stdout);
213 sgSetVec3( sgrollvec, 0.0, 0.0, 1.0 );
214 sgMat4 sgPHI; // roll
215 sgMakeRotMat4( sgPHI, f.get_Phi() * RAD_TO_DEG, sgrollvec );
217 MAT3_SET_VEC(vec, 0.0, 1.0, 0.0);
218 MAT3rotate(TMP, vec, f.get_Theta());
219 // cout << "Pitch matrix" << endl;;
220 // MAT3print(TMP, stdout);
222 // cout << "tmp rotation matrix, R:" << endl;;
223 // MAT3print(R, stdout);
226 sgSetVec3( sgpitchvec, 0.0, 1.0, 0.0 );
227 sgMat4 sgTHETA; // pitch
228 sgMakeRotMat4( sgTHETA, f.get_Theta() * RAD_TO_DEG,
232 sgMultMat4( sgROT, sgPHI, sgTHETA );
234 MAT3_SET_VEC(vec, 1.0, 0.0, 0.0);
235 MAT3rotate(TMP, vec, -f.get_Psi());
236 // cout << "Yaw matrix" << endl;
237 // MAT3print(TMP, stdout);
238 MAT3mult(LOCAL, R, TMP);
239 // cout << "LOCAL matrix:" << endl;
240 // MAT3print(LOCAL, stdout);
243 sgSetVec3( sgyawvec, 1.0, 0.0, 0.0 );
244 sgMat4 sgPSI; // pitch
245 sgMakeRotMat4( sgPSI, -f.get_Psi() * RAD_TO_DEG, sgyawvec );
247 sgMultMat4( sgLOCAL, sgROT, sgPSI );
248 // cout << "sgLOCAL matrix" << endl;
249 // print_sgMat4( sgLOCAL );
251 // Derive the local UP transformation matrix based on *geodetic*
253 MAT3_SET_VEC(vec, 0.0, 0.0, 1.0);
254 MAT3rotate(R, vec, f.get_Longitude()); // R = rotate about Z axis
255 // printf("Longitude matrix\n");
256 // MAT3print(R, stdout);
258 MAT3_SET_VEC(vec, 0.0, 1.0, 0.0);
259 MAT3mult_vec(vec, vec, R);
260 MAT3rotate(TMP, vec, -f.get_Latitude()); // TMP = rotate about X axis
261 // printf("Latitude matrix\n");
262 // MAT3print(TMP, stdout);
264 MAT3mult(UP, R, TMP);
265 // cout << "Local up matrix" << endl;;
266 // MAT3print(UP, stdout);
269 f.get_Longitude() * RAD_TO_DEG,
271 -f.get_Latitude() * RAD_TO_DEG );
273 cout << "FG derived UP matrix using sg routines" << endl;
277 for ( i = 0; i < 4; i++ ) {
278 for ( j = 0; j < 4; j++ ) {
279 print[i][j] = sgUP[i][j];
282 MAT3print( print, stdout);
285 MAT3_SET_VEC(local_up, 1.0, 0.0, 0.0);
286 MAT3mult_vec(local_up, local_up, UP);
288 // printf( "Local Up = (%.4f, %.4f, %.4f)\n",
289 // local_up[0], local_up[1], local_up[2]);
291 // Alternative method to Derive local up vector based on
292 // *geodetic* coordinates
293 // alt_up = fgPolarToCart(FG_Longitude, FG_Latitude, 1.0);
294 // printf( " Alt Up = (%.4f, %.4f, %.4f)\n",
295 // alt_up.x, alt_up.y, alt_up.z);
297 // Calculate the VIEW matrix
298 MAT3mult(VIEW, LOCAL, UP);
299 // cout << "VIEW matrix" << endl;;
300 // MAT3print(VIEW, stdout);
302 sgMat4 sgTMP, sgTMP2;
303 sgMultMat4( sgTMP, sgLOCAL, sgUP );
305 // generate the sg view up vector
307 sgSetVec3( vec1, 1.0, 0.0, 0.0 );
308 sgXformVec3( sgview_up, vec1, sgTMP );
310 // generate the view offset matrix
311 sgMakeRotMat4( sgVIEW_OFFSET, view_offset * RAD_TO_DEG, sgview_up );
312 // cout << "sgVIEW_OFFSET matrix" << endl;
313 // print_sgMat4( sgVIEW_OFFSET );
315 sgMultMat4( sgTMP2, sgTMP, sgVIEW_OFFSET );
316 sgMultMat4( sgVIEW_ROT, sgLARC_TO_SSG, sgTMP2 );
318 sgMakeTransMat4( sgTRANS, view_pos.x(), view_pos.y(), view_pos.z() );
320 sgMultMat4( sgVIEW, sgVIEW_ROT, sgTRANS );
322 // FGMat4Wrapper tmp;
323 // sgCopyMat4( tmp.m, sgVIEW );
324 // follow.push_back( tmp );
326 // generate the current up, forward, and fwrd-view vectors
327 MAT3_SET_VEC(vec, 1.0, 0.0, 0.0);
328 MAT3mult_vec(view_up, vec, VIEW);
331 cout << "FG derived VIEW matrix using sg routines" << endl;
335 for ( i = 0; i < 4; i++ ) {
336 for ( j = 0; j < 4; j++ ) {
337 print[i][j] = sgVIEW[i][j];
340 MAT3print( print, stdout);
343 MAT3_SET_VEC(vec, 0.0, 0.0, 1.0);
344 MAT3mult_vec(forward, vec, VIEW);
345 // printf( "Forward vector is (%.2f,%.2f,%.2f)\n", forward[0], forward[1],
348 MAT3rotate(TMP, view_up, view_offset);
349 MAT3mult_vec(view_forward, forward, TMP);
351 // make a vector to the current view position
352 MAT3_SET_VEC(v0, view_pos.x(), view_pos.y(), view_pos.z());
354 // Given a vector pointing straight down (-Z), map into onto the
355 // local plane representing "horizontal". This should give us the
356 // local direction for moving "south".
357 MAT3_SET_VEC(minus_z, 0.0, 0.0, -1.0);
358 map_vec_onto_cur_surface_plane(local_up, v0, minus_z, surface_south);
359 MAT3_NORMALIZE_VEC(surface_south, ntmp);
360 // printf( "Surface direction directly south %.2f %.2f %.2f\n",
361 // surface_south[0], surface_south[1], surface_south[2]);
363 // now calculate the surface east vector
364 MAT3rotate(TMP, view_up, FG_PI_2);
365 MAT3mult_vec(surface_east, surface_south, TMP);
366 // printf( "Surface direction directly east %.2f %.2f %.2f\n",
367 // surface_east[0], surface_east[1], surface_east[2]);
368 // printf( "Should be close to zero = %.2f\n",
369 // MAT3_DOT_PRODUCT(surface_south, surface_east));
374 FGView::~FGView( void ) {