1
0
Fork 0
flightgear/src/Main/viewer_lookat.cxx
curt 2b056c8452 This set of changes touches a *lot* of files. The main goal here is to
fix startup sequence problems where we initialize the FDM before we know
the desired starting altitude.

These changes delay fdm initialization until the local tile has been loaded
and we can do a real intersection and find the true ground elevation.

In order to do this, I depend more on the property manager as glue, rather
than the FGInterface.

There are some glitches still when switching to a new airport or reseting
the sim.  I will work on addressing these, but I need to commit the changes
so far to keep in sync with other developers.
2001-10-28 16:16:30 +00:00

239 lines
7.5 KiB
C++

// viewer_lookat.hxx -- class for managing a "look at" viewer in
// the flightgear world.
//
// Written by Curtis Olson, started October 2000.
//
// Copyright (C) 2000 Curtis L. Olson - curt@flightgear.org
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// $Id$
#include <simgear/compiler.h>
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <plib/ssg.h> // plib include
#include <simgear/constants.h>
#include <simgear/debug/logstream.hxx>
#include <simgear/math/point3d.hxx>
#include <simgear/math/polar3d.hxx>
#include <simgear/math/sg_geodesy.hxx>
#include <simgear/math/vector.hxx>
#include <Scenery/scenery.hxx>
#include "globals.hxx"
#include "viewer_lookat.hxx"
// Constructor
FGViewerLookAt::FGViewerLookAt( void )
{
set_reverse_view_offset(true);
}
void fgMakeLookAtMat4 ( sgMat4 dst, const sgVec3 eye, const sgVec3 center,
const sgVec3 up )
{
// Caveats:
// 1) In order to compute the line of sight, the eye point must not be equal
// to the center point.
// 2) The up vector must not be parallel to the line of sight from the eye
// to the center point.
/* Compute the direction vectors */
sgVec3 x,y,z;
/* Y vector = center - eye */
sgSubVec3 ( y, center, eye ) ;
/* Z vector = up */
sgCopyVec3 ( z, up ) ;
/* X vector = Y cross Z */
sgVectorProductVec3 ( x, y, z ) ;
/* Recompute Z = X cross Y */
sgVectorProductVec3 ( z, x, y ) ;
/* Normalize everything */
sgNormaliseVec3 ( x ) ;
sgNormaliseVec3 ( y ) ;
sgNormaliseVec3 ( z ) ;
/* Build the matrix */
#define M(row,col) dst[row][col]
M(0,0) = x[0]; M(0,1) = x[1]; M(0,2) = x[2]; M(0,3) = 0.0;
M(1,0) = y[0]; M(1,1) = y[1]; M(1,2) = y[2]; M(1,3) = 0.0;
M(2,0) = z[0]; M(2,1) = z[1]; M(2,2) = z[2]; M(2,3) = 0.0;
M(3,0) = eye[0]; M(3,1) = eye[1]; M(3,2) = eye[2]; M(3,3) = 1.0;
#undef M
}
#if 0
// convert sgMat4 to MAT3 and print
static void print_sgMat4( sgMat4 &in) {
int i, j;
for ( i = 0; i < 4; i++ ) {
for ( j = 0; j < 4; j++ ) {
printf("%10.4f ", in[i][j]);
}
cout << endl;
}
}
#endif
// Update the view parameters
void FGViewerLookAt::update() {
Point3D tmp;
sgVec3 minus_z;
// convert to geocentric coordinates
double geoc_lat;
sgGeodToGeoc( geod_view_pos[1], geod_view_pos[2],
&sea_level_radius, &geoc_lat );
// calculate the cartesion coords of the current lat/lon/0 elev
Point3D p = Point3D( geod_view_pos[0], geoc_lat, sea_level_radius );
tmp = sgPolarToCart3d(p) - scenery.get_center();
sgSetVec3( zero_elev, tmp[0], tmp[1], tmp[2] );
// calculate view position in current FG view coordinate system
// p.lon & p.lat are already defined earlier, p.radius was set to
// the sea level radius, so now we add in our altitude.
if ( geod_view_pos[2] > (scenery.get_cur_elev() + 0.5 * SG_METER_TO_FEET) ) {
p.setz( p.radius() + geod_view_pos[2] );
} else {
p.setz( p.radius() + scenery.get_cur_elev() + 0.5 * SG_METER_TO_FEET );
}
tmp = sgPolarToCart3d(p);
sgdSetVec3( abs_view_pos, tmp[0], tmp[1], tmp[2] );
// view_pos = abs_view_pos - scenery.center;
sgdVec3 sc;
sgdSetVec3( sc,
scenery.get_center().x(),
scenery.get_center().y(),
scenery.get_center().z() );
sgdVec3 vp;
sgdSubVec3( vp, abs_view_pos, sc );
sgSetVec3( view_pos, vp );
sgVec3 tmp_offset;
sgCopyVec3( tmp_offset, pilot_offset );
SG_LOG( SG_VIEW, SG_DEBUG, "tmp offset = "
<< tmp_offset[0] << "," << tmp_offset[1] << ","
<< tmp_offset[2] );
//!!!!!!!!!!!!!!!!!!!
// THIS IS THE EXPERIMENTAL VIEWING ANGLE SHIFTER
// THE MAJORITY OF THE WORK IS DONE IN GUI.CXX
extern float GuiQuat_mat[4][4];
sgXformPnt3( tmp_offset, tmp_offset, GuiQuat_mat );
SG_LOG( SG_VIEW, SG_DEBUG, "tmp_offset = "
<< tmp_offset[0] << "," << tmp_offset[1] << ","
<< tmp_offset[2] );
sgAddVec3( view_pos, tmp_offset );
// !!!!!!!!!! testing
// sgAddVec3( view_pos, pilot_offset );
SG_LOG( SG_VIEW, SG_DEBUG, "sea level radius = " << sea_level_radius );
SG_LOG( SG_VIEW, SG_DEBUG, "Polar view pos = " << p );
SG_LOG( SG_VIEW, SG_DEBUG, "Absolute view pos = "
<< abs_view_pos[0] << ","
<< abs_view_pos[1] << ","
<< abs_view_pos[2] );
SG_LOG( SG_VIEW, SG_DEBUG, "Relative view pos = "
<< view_pos[0] << "," << view_pos[1] << "," << view_pos[2] );
SG_LOG( SG_VIEW, SG_DEBUG, "pilot offset = "
<< pilot_offset[0] << "," << pilot_offset[1] << ","
<< pilot_offset[2] );
SG_LOG( SG_VIEW, SG_DEBUG, "view forward = "
<< view_forward[0] << "," << view_forward[1] << ","
<< view_forward[2] );
SG_LOG( SG_VIEW, SG_DEBUG, "view up = "
<< view_up[0] << "," << view_up[1] << ","
<< view_up[2] );
// Make the VIEW matrix.
fgMakeLookAtMat4( VIEW, view_pos, view_forward, view_up );
// cout << "VIEW matrix" << endl;
// print_sgMat4( VIEW );
// the VIEW matrix includes both rotation and translation. Let's
// knock out the translation part to make the VIEW_ROT matrix
sgCopyMat4( VIEW_ROT, VIEW );
VIEW_ROT[3][0] = VIEW_ROT[3][1] = VIEW_ROT[3][2] = 0.0;
// Make the world up rotation matrix
sgMakeRotMat4( UP,
geod_view_pos[0] * SGD_RADIANS_TO_DEGREES,
0.0,
-geod_view_pos[1] * SGD_RADIANS_TO_DEGREES );
// use a clever observation into the nature of our tranformation
// matrix to grab the world_up vector
sgSetVec3( world_up, UP[0][0], UP[0][1], UP[0][2] );
// cout << "World Up = " << world_up[0] << "," << world_up[1] << ","
// << world_up[2] << endl;
// Given a vector pointing straight down (-Z), map into onto the
// local plane representing "horizontal". This should give us the
// local direction for moving "south".
sgSetVec3( minus_z, 0.0, 0.0, -1.0 );
sgmap_vec_onto_cur_surface_plane(world_up, view_pos, minus_z,
surface_south);
sgNormalizeVec3(surface_south);
// cout << "Surface direction directly south " << surface_south[0] << ","
// << surface_south[1] << "," << surface_south[2] << endl;
// now calculate the surface east vector
#define USE_FAST_SURFACE_EAST
#ifdef USE_FAST_SURFACE_EAST
sgVec3 world_down;
sgNegateVec3(world_down, world_up);
sgVectorProductVec3(surface_east, surface_south, world_down);
#else
sgMakeRotMat4( TMP, SGD_PI_2 * SGD_RADIANS_TO_DEGREES, world_up );
// cout << "sgMat4 TMP" << endl;
// print_sgMat4( TMP );
sgXformVec3(surface_east, surface_south, TMP);
#endif // USE_FAST_SURFACE_EAST
// cout << "Surface direction directly east " << surface_east[0] << ","
// << surface_east[1] << "," << surface_east[2] << endl;
// cout << "Should be close to zero = "
// << sgScalarProductVec3(surface_south, surface_east) << endl;
set_clean();
}
// Destructor
FGViewerLookAt::~FGViewerLookAt( void ) {
}