6f802959ce
CameraGroup supports cameras opened in different windows or in the same window, with flexible view and perspective specification. Clean up mouse click handling via osgViewer. Don't let any camera "have focus;" this forces events to be reported in window coordinates and simplifies life. Don't use the osgViewer::View::requestWarpPointer method; instead use our own code which only deals with window coordinates. Make glut and sdl versions work with CameraGroup too.
403 lines
15 KiB
C++
403 lines
15 KiB
C++
// viewer.hxx -- class for managing a viewer in the flightgear world.
|
|
//
|
|
// Written by Curtis Olson, started August 1997.
|
|
// overhaul started October 2000.
|
|
// partially rewritten by Jim Wilson jim@kelcomaine.com using interface
|
|
// by David Megginson March 2002
|
|
//
|
|
// Copyright (C) 1997 - 2000 Curtis L. Olson - http://www.flightgear.org/~curt
|
|
//
|
|
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
//
|
|
// $Id$
|
|
|
|
|
|
#ifndef _VIEWER_HXX
|
|
#define _VIEWER_HXX
|
|
|
|
|
|
#ifndef __cplusplus
|
|
# error This library requires C++
|
|
#endif
|
|
|
|
namespace flightgear
|
|
{
|
|
class CameraGroup;
|
|
}
|
|
|
|
#include <osg/ref_ptr>
|
|
|
|
#include <simgear/compiler.h>
|
|
#include <simgear/constants.h>
|
|
#include <simgear/structure/subsystem_mgr.hxx>
|
|
#include <simgear/scene/model/location.hxx>
|
|
|
|
#include <plib/sg.h> // plib include
|
|
|
|
#define FG_FOV_MIN 0.1
|
|
#define FG_FOV_MAX 179.9
|
|
|
|
enum fgViewType {
|
|
FG_LOOKFROM = 0,
|
|
FG_LOOKAT = 1
|
|
};
|
|
|
|
// Define a structure containing view information
|
|
class FGViewer : public SGSubsystem {
|
|
|
|
public:
|
|
|
|
enum fgScalingType { // nominal Field Of View actually applies to ...
|
|
FG_SCALING_WIDTH, // window width
|
|
FG_SCALING_MAX // max(width, height)
|
|
// FG_SCALING_G_MEAN, // geometric_mean(width, height)
|
|
// FG_SCALING_INDEPENDENT // whole screen
|
|
};
|
|
|
|
// Constructor
|
|
FGViewer( fgViewType Type, bool from_model, int from_model_index,
|
|
bool at_model, int at_model_index,
|
|
double damp_roll, double damp_pitch, double damp_heading,
|
|
double x_offset_m, double y_offset_m, double z_offset_m,
|
|
double heading_offset_deg, double pitch_offset_deg,
|
|
double roll_offset_deg,
|
|
double fov_deg, double aspect_ratio_multiplier,
|
|
double target_x_offset_m, double target_y_offset_m,
|
|
double target_z_offset_m, double near_m, bool internal );
|
|
|
|
// Destructor
|
|
virtual ~FGViewer( void );
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Part 1: standard SGSubsystem implementation.
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
virtual void init ();
|
|
virtual void bind ();
|
|
virtual void unbind ();
|
|
void update (double dt);
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Part 2: user settings.
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
virtual fgViewType getType() const { return _type; }
|
|
virtual void setType( int type );
|
|
|
|
virtual bool getInternal() const { return _internal; }
|
|
virtual void setInternal( bool internal );
|
|
|
|
// Reference geodetic position of view from position...
|
|
// These are the actual aircraft position (pilot in
|
|
// pilot view, model in model view).
|
|
// FIXME: the model view position (ie target positions)
|
|
// should be in the model class.
|
|
virtual double getLongitude_deg () const { return _lon_deg; }
|
|
virtual double getLatitude_deg () const { return _lat_deg; }
|
|
virtual double getAltitudeASL_ft () const { return _alt_ft; }
|
|
virtual void setLongitude_deg (double lon_deg);
|
|
virtual void setLatitude_deg (double lat_deg);
|
|
virtual void setAltitude_ft (double alt_ft);
|
|
virtual void setPosition (double lon_deg, double lat_deg, double alt_ft);
|
|
|
|
// Reference geodetic target position...
|
|
virtual double getTargetLongitude_deg () const { return _target_lon_deg; }
|
|
virtual double getTargetLatitude_deg () const { return _target_lat_deg; }
|
|
virtual double getTargetAltitudeASL_ft () const { return _target_alt_ft; }
|
|
virtual void setTargetLongitude_deg (double lon_deg);
|
|
virtual void setTargetLatitude_deg (double lat_deg);
|
|
virtual void setTargetAltitude_ft (double alt_ft);
|
|
virtual void setTargetPosition (double lon_deg, double lat_deg, double alt_ft);
|
|
|
|
|
|
|
|
|
|
// Position offsets from reference
|
|
// These offsets position they "eye" in the scene according to a given
|
|
// location. For example in pilot view they are used to position the
|
|
// head inside the aircraft.
|
|
// Note that in pilot view these are applied "before" the orientation
|
|
// rotations (see below) so that the orientation rotations have the
|
|
// effect of the pilot staying in his seat and "looking out" in
|
|
// different directions.
|
|
// In chase view these are applied "after" the application of the
|
|
// orientation rotations listed below. This has the effect of the
|
|
// eye moving around and "looking at" the object (model) from
|
|
// different angles.
|
|
virtual double getXOffset_m () const { return _offset_m.x(); }
|
|
virtual double getYOffset_m () const { return _offset_m.y(); }
|
|
virtual double getZOffset_m () const { return _offset_m.z(); }
|
|
virtual double getTargetXOffset_m () const { return _target_offset_m.x(); }
|
|
virtual double getTargetYOffset_m () const { return _target_offset_m.y(); }
|
|
virtual double getTargetZOffset_m () const { return _target_offset_m.z(); }
|
|
virtual void setXOffset_m (double x_offset_m);
|
|
virtual void setYOffset_m (double y_offset_m);
|
|
virtual void setZOffset_m (double z_offset_m);
|
|
virtual void setTargetXOffset_m (double x_offset_m);
|
|
virtual void setTargetYOffset_m (double y_offset_m);
|
|
virtual void setTargetZOffset_m (double z_offset_m);
|
|
virtual void setPositionOffsets (double x_offset_m,
|
|
double y_offset_m,
|
|
double z_offset_m);
|
|
|
|
|
|
|
|
|
|
// Reference orientation rotations...
|
|
// These are rotations that represent the plane attitude effect on
|
|
// the view (in Pilot view). IE The view frustrum rotates as the plane
|
|
// turns, pitches, and rolls.
|
|
// In model view (lookat/chaseview) these end up changing the angle that
|
|
// the eye is looking at the ojbect (ie the model).
|
|
// FIXME: the FGModel class should have its own version of these so that
|
|
// it can generate it's own model rotations.
|
|
virtual double getRoll_deg () const { return _roll_deg; }
|
|
virtual double getPitch_deg () const {return _pitch_deg; }
|
|
virtual double getHeading_deg () const {return _heading_deg; }
|
|
virtual void setRoll_deg (double roll_deg);
|
|
virtual void setPitch_deg (double pitch_deg);
|
|
virtual void setHeading_deg (double heading_deg);
|
|
virtual void setOrientation (double roll_deg, double pitch_deg, double heading_deg);
|
|
virtual double getTargetRoll_deg () const { return _target_roll_deg; }
|
|
virtual double getTargetPitch_deg () const {return _target_pitch_deg; }
|
|
virtual double getTargetHeading_deg () const {return _target_heading_deg; }
|
|
virtual void setTargetRoll_deg (double roll_deg);
|
|
virtual void setTargetPitch_deg (double pitch_deg);
|
|
virtual void setTargetHeading_deg (double heading_deg);
|
|
virtual void setTargetOrientation (double roll_deg, double pitch_deg, double heading_deg);
|
|
|
|
|
|
|
|
|
|
// Orientation offsets rotations from reference orientation.
|
|
// Goal settings are for smooth transition from prior
|
|
// offset when changing view direction.
|
|
// These offsets are in ADDITION to the orientation rotations listed
|
|
// above.
|
|
// In pilot view they are applied after the position offsets in order to
|
|
// give the effect of the pilot looking around.
|
|
// In lookat view they are applied before the position offsets so that
|
|
// the effect is the eye moving around looking at the object (ie the model)
|
|
// from different angles.
|
|
virtual double getRollOffset_deg () const { return _roll_offset_deg; }
|
|
virtual double getPitchOffset_deg () const { return _pitch_offset_deg; }
|
|
virtual double getHeadingOffset_deg () const { return _heading_offset_deg; }
|
|
virtual double getGoalRollOffset_deg () const { return _goal_roll_offset_deg; }
|
|
virtual double getGoalPitchOffset_deg () const { return _goal_pitch_offset_deg; }
|
|
virtual double getGoalHeadingOffset_deg () const {return _goal_heading_offset_deg; }
|
|
virtual void setRollOffset_deg (double roll_offset_deg);
|
|
virtual void setPitchOffset_deg (double pitch_offset_deg);
|
|
virtual void setHeadingOffset_deg (double heading_offset_deg);
|
|
virtual void setGoalRollOffset_deg (double goal_roll_offset_deg);
|
|
virtual void setGoalPitchOffset_deg (double goal_pitch_offset_deg);
|
|
virtual void setGoalHeadingOffset_deg (double goal_heading_offset_deg);
|
|
virtual void setOrientationOffsets (double roll_offset_deg,
|
|
double heading_offset_deg,
|
|
double pitch_offset_deg);
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Part 3: output vectors and matrices in FlightGear coordinates.
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
// Vectors and positions...
|
|
|
|
// Get zero elev
|
|
const SGVec3d& get_zero_elev() {if ( _dirty ) { recalc(); } return _zero_elev; }
|
|
// Get world up vector
|
|
const SGVec3f& get_world_up() {if ( _dirty ) { recalc(); } return _world_up; }
|
|
// Get surface east vector
|
|
const SGVec3f& get_surface_east() { if ( _dirty ) { recalc(); } return _surface_east; }
|
|
// Get surface south vector
|
|
const SGVec3f& get_surface_south() {if ( _dirty ) { recalc(); } return _surface_south; }
|
|
|
|
const SGVec3d& get_view_pos() { if ( _dirty ) { recalc(); } return _absolute_view_pos; }
|
|
const SGVec3d& getViewPosition() { if ( _dirty ) { recalc(); } return _absolute_view_pos; }
|
|
const SGQuatd& getViewOrientation() { if ( _dirty ) { recalc(); } return mViewOrientation; }
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Part 4: View and frustrum data setters and getters
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
virtual void set_fov( double fov_deg ) {
|
|
_fov_deg = fov_deg;
|
|
}
|
|
virtual double get_fov() const { return _fov_deg; }
|
|
virtual double get_h_fov(); // Get horizontal fov, in degrees.
|
|
virtual double get_v_fov(); // Get vertical fov, in degrees.
|
|
|
|
virtual void set_aspect_ratio( double r ) {
|
|
_aspect_ratio = r;
|
|
}
|
|
virtual double get_aspect_ratio() const { return _aspect_ratio; }
|
|
|
|
virtual void set_aspect_ratio_multiplier( double m ) {
|
|
_aspect_ratio_multiplier = m;
|
|
}
|
|
virtual double get_aspect_ratio_multiplier() const {
|
|
return _aspect_ratio_multiplier;
|
|
}
|
|
|
|
virtual double getNear_m () const { return _ground_level_nearplane_m; }
|
|
inline void setNear_m (double near_m) {
|
|
_ground_level_nearplane_m = near_m;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Part 5: misc setters and getters
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
inline void set_dirty() { _dirty = true; }
|
|
inline void set_clean() { _dirty = false; }
|
|
|
|
// return eye location...
|
|
virtual SGLocation * getSGLocation () const { return _location; }
|
|
|
|
|
|
private:
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
// private data //
|
|
//////////////////////////////////////////////////////////////////
|
|
|
|
// flag forcing a recalc of derived view parameters
|
|
bool _dirty;
|
|
|
|
SGQuatd mViewOrientation;
|
|
SGVec3d _absolute_view_pos;
|
|
|
|
double _lon_deg;
|
|
double _lat_deg;
|
|
double _alt_ft;
|
|
double _target_lon_deg;
|
|
double _target_lat_deg;
|
|
double _target_alt_ft;
|
|
|
|
double _roll_deg;
|
|
double _pitch_deg;
|
|
double _heading_deg;
|
|
double _target_roll_deg;
|
|
double _target_pitch_deg;
|
|
double _target_heading_deg;
|
|
|
|
double _damp_sync;
|
|
double _damp_roll;
|
|
double _damp_pitch;
|
|
double _damp_heading;
|
|
|
|
double _damped_roll_deg;
|
|
double _damped_pitch_deg;
|
|
double _damped_heading_deg;
|
|
|
|
// Position offsets from FDM origin. The X axis is positive
|
|
// out the tail, Y is out the right wing, and Z is positive up.
|
|
// distance in meters
|
|
SGVec3d _offset_m;
|
|
|
|
// Target offsets from FDM origin (for "lookat" targets) The X
|
|
// axis is positive out the tail, Y is out the right wing, and Z
|
|
// is positive up. distance in meters
|
|
SGVec3d _target_offset_m;
|
|
|
|
|
|
// orientation offsets from reference (_goal* are for smoothed transitions)
|
|
double _roll_offset_deg;
|
|
double _pitch_offset_deg;
|
|
double _heading_offset_deg;
|
|
double _goal_roll_offset_deg;
|
|
double _goal_pitch_offset_deg;
|
|
double _goal_heading_offset_deg;
|
|
|
|
// used to set nearplane when at ground level for this view
|
|
double _ground_level_nearplane_m;
|
|
|
|
fgViewType _type;
|
|
fgScalingType _scaling_type;
|
|
|
|
// internal view (e.g. cockpit) flag
|
|
bool _internal;
|
|
|
|
// view is looking from a model
|
|
bool _from_model;
|
|
int _from_model_index; // number of model (for multi model)
|
|
|
|
// view is looking at a model
|
|
bool _at_model;
|
|
int _at_model_index; // number of model (for multi model)
|
|
|
|
SGLocation * _location;
|
|
SGLocation * _target_location;
|
|
|
|
// the nominal field of view (angle, in degrees)
|
|
double _fov_deg;
|
|
|
|
// Ratio of window width and height; height = width *
|
|
// aspect_ratio. This value is automatically calculated based on
|
|
// window dimentions.
|
|
double _aspect_ratio;
|
|
|
|
// default = 1.0, this value is user configurable and is
|
|
// multiplied into the aspect_ratio to get the actual vertical fov
|
|
double _aspect_ratio_multiplier;
|
|
|
|
// cartesion coordinates of current lon/lat if at sea level
|
|
SGVec3d _zero_elev;
|
|
|
|
// surface vector heading south
|
|
SGVec3f _surface_south;
|
|
|
|
// surface vector heading east (used to unambiguously align sky
|
|
// with sun)
|
|
SGVec3f _surface_east;
|
|
|
|
// world up vector (normal to the plane tangent to the earth's
|
|
// surface at the spot we are directly above
|
|
SGVec3f _world_up;
|
|
|
|
// camera group controled by this view
|
|
osg::ref_ptr<flightgear::CameraGroup> _cameraGroup;
|
|
//////////////////////////////////////////////////////////////////
|
|
// private functions //
|
|
//////////////////////////////////////////////////////////////////
|
|
|
|
void recalc ();
|
|
void recalcLookFrom();
|
|
void recalcLookAt();
|
|
void dampEyeData(double &roll_deg, double &pitch_deg, double &heading_deg);
|
|
|
|
// add to _heading_offset_deg
|
|
inline void incHeadingOffset_deg( double amt ) {
|
|
set_dirty();
|
|
_heading_offset_deg += amt;
|
|
}
|
|
|
|
// add to _pitch_offset_deg
|
|
inline void incPitchOffset_deg( double amt ) {
|
|
set_dirty();
|
|
_pitch_offset_deg += amt;
|
|
}
|
|
|
|
// add to _roll_offset_deg
|
|
inline void incRollOffset_deg( double amt ) {
|
|
set_dirty();
|
|
_roll_offset_deg += amt;
|
|
}
|
|
|
|
};
|
|
|
|
|
|
#endif // _VIEWER_HXX
|