extern FGInterface cur_view_fdm;
GLubyte *hiResScreenCapture( int multiplier )
{
- float oldfov = fgGetDouble("/sim/field-of-view");
+ float oldfov = fgGetDouble("/sim/current-view/field-of-view");
float fov = oldfov / multiplier;
FGViewer *v = globals->get_current_view();
- fgSetDouble("/sim/field-of-view", fov);
+ fgSetDouble("/sim/current-view/field-of-view", fov);
fgInitVisuals();
int cur_width = fgGetInt("/sim/startup/xsize");
int cur_height = fgGetInt("/sim/startup/ysize");
b1->copyBitmap( &b2, cur_width*x, cur_height*y );
}
}
- fgSetDouble("/sim/field-of-view", oldfov);
+ fgSetDouble("/sim/current-view/field-of-view", oldfov);
return b1->getBitmap();
}
#endif
guiToggleMenu(); // Menu off by default
}
}
-
float max = 100.0f, float min = 0.0f);
~FloatSlider () {;}
-
- static void adj( puObject *);
+ static void adj( puObject *);
+
void updateText() {
sprintf( _text, "%05.2f", MyValue );
}
// adjust the TmpValue back to 0 to 1 range of pui widget
void setTmp() { TmpValue += 0.0f; }
+ void incTmp() { TmpValue += 0.0001f; setTmp(); }
+ void decTmp() { TmpValue -= 0.0001f; setTmp(); }
+
// adjust actual "setting" value back to fraction for pui widget
void init( float f ) {
if (f > maxValue) f = maxValue;
void FloatSlider::adj( puObject *hs )
{
- FloatSlider *slider = (FloatSlider *)hs->getUserData();
+ FloatSlider *slider = (FloatSlider *)hs;
slider->getValue ( slider->getTmp() );
slider->setTmp();
slider->set();
FloatSlider::FloatSlider ( int x, int y, int sz, float f, const char *title,
float max, float min ) : puSlider( x, y, sz, FALSE )
{
- setUserData( this );
maxValue = max;
minValue = min;
origValue = f;
init(f);
setDelta ( 0.01 );
setCBMode ( PUSLIDER_DELTA ) ;
- setCallback ( adj ) ;
strcpy ( _title, title);
setLabel ( _title );
- setLabelPlace ( PUPLACE_LEFT );
+ setLabelPlace ( PUPLACE_LEFT );
setLegend(_text);
// setLegendPlace( PUPLACE_RIGHT );
}
// adjust the TmpValue back to 0 to 1 range of pui widget
void setTmp() { TmpValue += 0.5f; }
+
+ void incTmp() { TmpValue += 0.0001f; setTmp(); }
+ void decTmp() { TmpValue -= 0.0001f; setTmp(); }
// adjust actual "setting" value back to fraction for pui widget
// double the range from -max <-> max
void FloatDial::adj( puObject *hs )
{
- FloatDial *dial = (FloatDial *)hs->getUserData();
+ FloatDial *dial = (FloatDial *)hs;
dial->getValue ( dial->getTmp() );
dial->setTmp();
dial->set();
FloatDial::FloatDial ( int x, int y, int sz, float f, const char *title,
float max, float min ) : puDial( x, y, sz )
{
- setUserData( this );
maxValue = max;
minValue = min;
origValue = f;
init(f);
setDelta ( 0.01 );
setCBMode ( PUSLIDER_DELTA ) ;
- setCallback ( adj ) ;
strcpy ( _title, title);
setLabel ( _title );
setLabelPlace ( PUPLACE_LEFT );
class sgVec3Slider : public puDialogBox
{
+ static void handle_arrow(puObject *p_obj);
+ static void heading_adj(puObject *p_obj);
+ static void pitch_adj(puObject *p_obj);
+ static void radius_adj(puObject *p_obj);
static void goAway(puObject *p_obj);
static void reset(puObject *p_obj);
static void cancel(puObject *p_obj);
puOneShot *OkButton;
puOneShot *ResetButton;
puOneShot *CancelButton;
+ puArrowButton *right_arrow;
+ puArrowButton *left_arrow;
sgVec3 Vec, SaveVec;
public:
const char *title = "Vector Adjuster",
const char *Xtitle = "Heading",
const char *Ytitle = "Pitch",
- const char *Ztitle = "Radius" );
+ const char *Ztitle = "Radius " );
~sgVec3Slider () {;}
+
// calc the property Vec with the actual point on sphere
void setVec()
{
};
// class constructor
-sgVec3Slider::sgVec3Slider ( int x, int y, sgVec3 vec, const char *title,
+sgVec3Slider::sgVec3Slider ( int x, int y, sgVec3 cart, const char *title,
const char *Xtitle,
const char *Ytitle,
const char *Ztitle ): puDialogBox ( x, y )
{
puFont LegendFont, LabelFont;
puGetDefaultFonts ( &LegendFont, &LabelFont );
-
int fudge = 20;
+ HeadingPitchRadiusFromVec3( Vec, cart);
+ sgVec3 vec;
+ sgSetVec3(vec, Vec[0], Vec[1], Vec[2]);
+
int labelW = LabelFont.getStringWidth(Xtitle);
labelW = SG_MAX2( labelW, LabelFont.getStringWidth(Ytitle));
labelW = SG_MAX2( labelW, LabelFont.getStringWidth(Ztitle));
/* heading */
HS0 = new FloatDial ( dialer_x, dialer_y, dialer_size, vec[0], Xtitle, 180.0f, -180.0f );
dialer_x = dialer_x + 170;
+ HS0->setUserData (this);
+ HS0->setCallback ( heading_adj ) ;
/* pitch */
HS1 = new FloatDial ( dialer_x, dialer_y, dialer_size, vec[1], Ytitle, 89.99f, -89.99f );
+ HS1->setUserData (this);
+ HS1->setCallback ( pitch_adj ) ;
/* radius */
- HS2 = new FloatSlider ( slider_x, slider_y, slider_width, vec[2], Ztitle, 100.0f, 0.0f );
+ HS2 = new FloatSlider ( slider_x+20, slider_y, slider_width-40, vec[2], Ztitle, 100.0f, 0.0f );
+ HS2->setUserData (this);
+ HS2->setCallback ( radius_adj );
+
+ right_arrow = new puArrowButton ( slider_x + slider_width - 20, slider_y + 1, slider_x + slider_width, slider_y+21, PUARROW_RIGHT ) ;
+ right_arrow->setUserData ( HS2 ) ;
+ right_arrow->setCallback ( handle_arrow ) ;
+
+ left_arrow = new puArrowButton ( slider_x, slider_y + 1, slider_x+20, slider_y+21, PUARROW_LEFT ) ;
+ left_arrow->setUserData ( HS2 ) ;
+ left_arrow->setCallback ( handle_arrow ) ;
TitleText = new puText( 130, DialogHeight - 40);
TitleText->setLabel("Pilot Offset");
CancelButton-> setLegend ( gui_msg_CANCEL );
CancelButton-> setCallback ( cancel );
- ResetButton = new puOneShot ( 220+fudge, 20, 280+fudge, 50 );
- ResetButton-> setUserData( this );
- ResetButton-> setLegend ( gui_msg_RESET );
- ResetButton-> setCallback ( reset );
+// renabling this button requires binding in the sim/view[?]/config/?-offset-m values
+// ResetButton = new puOneShot ( 220+fudge, 20, 280+fudge, 50 );
+// ResetButton-> setUserData( this );
+// ResetButton-> setLegend ( gui_msg_RESET );
+// ResetButton-> setCallback ( reset );
FG_FINALIZE_PUI_DIALOG( this );
}
+void sgVec3Slider::handle_arrow(puObject *arrow)
+{
+ FloatSlider *slider = (FloatSlider *) arrow->getUserData();
+ if (((puArrowButton *)arrow)->getArrowType() == PUARROW_RIGHT)
+ slider->incTmp();
+ else
+ slider->decTmp();
+ slider->set();
+ slider->init( slider->get() );
+ sgVec3Slider *me = (sgVec3Slider *)slider->getUserData();
+ me->setVec();
+};
+
+void sgVec3Slider::heading_adj(puObject *p_obj)
+{
+ sgVec3Slider *me = (sgVec3Slider *)p_obj->getUserData();
+ me->HS0->adj((puObject *)me ->HS0 );
+ me->setVec();
+};
+
+void sgVec3Slider::pitch_adj(puObject *p_obj)
+{
+ sgVec3Slider *me = (sgVec3Slider *)p_obj->getUserData();
+ me->HS1->adj((puObject *)me ->HS1 );
+ me->setVec();
+};
+
+void sgVec3Slider::radius_adj(puObject *p_obj)
+{
+ sgVec3Slider *me = (sgVec3Slider *)p_obj->getUserData();
+ me ->HS2-> adj((puObject *)me ->HS2 );
+ me->setVec();
+};
+
void sgVec3Slider::goAway(puObject *p_obj)
{
sgVec3Slider *me = (sgVec3Slider *)p_obj->getUserData();
void sgVec3Slider::adjust(puObject *p_obj)
{
sgVec3Slider *me = (sgVec3Slider *)p_obj->getUserData();
+ heading_adj( me );
+ pitch_adj( me );
+ radius_adj( me );
+
+ sgVec3 cart;
+ sgSetVec3(cart,
+ fgGetFloat("/sim/current-view/x-offset-m"),
+ fgGetFloat("/sim/current-view/y-offset-m"),
+ fgGetFloat("/sim/current-view/z-offset-m")
+ );
+
+ HeadingPitchRadiusFromVec3( me->Vec, cart);
+
+ me -> getHS0() -> init(me->Vec[0]);
+ me -> getHS1() -> init(me->Vec[1]);
+ me -> getHS2() -> init(me->Vec[2]);
+
me -> getHS0() -> adj((puObject *)me -> getHS0());
me -> getHS1() -> adj((puObject *)me -> getHS1());
me -> getHS2() -> adj((puObject *)me -> getHS2());
static puObject *PO_vec = 0;
void PilotOffsetInit() {
- sgVec3 v;
- sgSetVec3(v,
- fgGetFloat("/sim/view[1]/default/pilot-offset/heading-deg"),
- fgGetFloat("/sim/view[1]/default/pilot-offset/pitch-deg"),
- fgGetFloat("/sim/view[1]/default/pilot-offset/radius-m")
+ sgVec3 cart;
+ sgSetVec3(cart,
+ fgGetFloat("/sim/current-view/x-offset-m"),
+ fgGetFloat("/sim/current-view/y-offset-m"),
+ fgGetFloat("/sim/current-view/z-offset-m")
);
-
- PilotOffsetInit(v);
+ PilotOffsetInit(cart);
}
-void PilotOffsetInit( sgVec3 vec )
+void PilotOffsetInit( sgVec3 cart )
{
// Only one of these things for now
if( PO_vec == 0 ) {
- /* make change so this gets done once for each vector */
- fgSetFloat("/sim/view[1]/current/pilot-offset/heading-deg",fgGetFloat("/sim/view[1]/default/pilot-offset/heading-deg"));
- fgSetFloat("/sim/view[1]/current/pilot-offset/pitch-deg",fgGetFloat("/sim/view[1]/default/pilot-offset/pitch-deg"));
- fgSetFloat("/sim/view[1]/current/pilot-offset/radius-m",fgGetFloat("/sim/view[1]/default/pilot-offset/radius-m"));
- sgVec3Slider *PO = new sgVec3Slider ( 200, 200, vec, "Pilot Offset" );
+ sgVec3Slider *PO = new sgVec3Slider ( 200, 200, cart, "Pilot Offset" );
PO_vec = PO;
// Bindings for Pilot Offset
- fgTie("/sim/view[1]/current/pilot-offset/heading-deg", getPilotOffsetHeadingDeg, setPilotOffsetHeadingDeg);
- fgTie("/sim/view[1]/current/pilot-offset/pitch-deg", getPilotOffsetPitchDeg, setPilotOffsetPitchDeg);
- fgTie("/sim/view[1]/current/pilot-offset/radius-m", getPilotOffsetRadiusM, setPilotOffsetRadiusM);
+ fgTie("/sim/current-view/x-offset-m", getPilotXOffset, setPilotXOffset);
+ fgTie("/sim/current-view/y-offset-m", getPilotYOffset, setPilotYOffset);
+ fgTie("/sim/current-view/z-offset-m", getPilotZOffset, setPilotZOffset);
}
}
PilotOffsetInit();
}
sgVec3Slider *me = (sgVec3Slider *)PO_vec -> getUserData();
- me -> stashVec();
me -> adjust( me );
+ me -> stashVec();
FG_PUSH_PUI_DIALOG( me );
}
PilotOffsetInit();
}
sgVec3Slider *me = (sgVec3Slider *)PO_vec -> getUserData();
- if( opt == 0 ) setting = me -> getHS0() -> get();
- if( opt == 1 ) setting = me -> getHS1() -> get();
- if( opt == 2 ) setting = me-> getHS2() -> get();
+ sgVec3 vec;
+ sgCopyVec3(vec, (float *) me->getVec());
+ if( opt == 0 ) setting = vec[0];
+ if( opt == 1 ) setting = vec[1];
+ if( opt == 2 ) setting = vec[2];
return( setting );
}
PilotOffsetInit();
}
sgVec3Slider *me = (sgVec3Slider *)PO_vec -> getUserData();
- if( opt == 0 ) me -> getHS0() -> init( setting );
- if( opt == 1 ) me -> getHS1() -> init( setting );
- if( opt == 2 ) me-> getHS2() -> init( setting );
+
+ sgVec3 HPR;
+ sgVec3 vec;
+ sgCopyVec3(vec, (float *) me->getVec());
+ if( opt == 0 ) vec[0] = setting;
+ if( opt == 1 ) vec[1] = setting;
+ if( opt == 2 ) vec[2] = setting;
+ HeadingPitchRadiusFromVec3 ( HPR, vec );
+ me -> getHS0() -> init( HPR[0] );
+ me -> getHS1() -> init( HPR[1] );
+ me -> getHS2() -> init( HPR[2] );
+ me -> stashVec();
}
// input Pitch == latitude of point on sphere
// input Radius == radius of sphere
-#define MIN_VIEW_OFFSET 5.0
+#define MIN_VIEW_OFFSET 0.001
void Vec3FromHeadingPitchRadius ( sgVec3 vec3, float heading, float pitch,
float radius )
{
vec3[1] = (SGfloat)( sh * cp ) * radius ; // Y
vec3[0] = (SGfloat)( sp ) * radius ; // Z
}
+
+// Convert to speherical coordinates for the dials
+
+void HeadingPitchRadiusFromVec3 ( sgVec3 hpr, sgVec3 vec3 )
+{
+ double x = vec3[0];
+ double y = vec3[1];
+ double z = vec3[2];
+ double Zx;
+ double Pr;
+
+ if (z == 0.0f) {
+ hpr[0] = 0;
+ hpr[1] = 0;
+ hpr[2] = 0;
+ } else {
+ if (fabs(y) < 0.001f)
+ y == 0.001f;
+
+ Zx = sqrt(y*y + z*z);
+
+ hpr[2] = sqrt(x*x + y*y + z*z);
+
+ Pr = Zx / hpr[2];
+ if (Pr > 1.0f)
+ hpr[1] = 0.0f;
+ else
+ hpr[1] = acos(Pr) * SGD_RADIANS_TO_DEGREES;
+ if (x < 0.0f)
+ hpr[1] *= -SGD_ONE;
+
+ if (z < 0.0f) {
+ hpr[0] = (SGD_PI - asin(y/Zx)) * SGD_RADIANS_TO_DEGREES;
+ } else {
+ hpr[0] = asin(y/Zx) * SGD_RADIANS_TO_DEGREES;
+ if (hpr[0] > 180) {
+ hpr[0] = 180 - hpr[0];
+ }
+ }
+ }
+}
void PilotOffsetInit( sgVec3 vec );
void PilotOffsetAdjust( puObject * );
void Vec3FromHeadingPitchRadius( sgVec3 vec3, float heading, float pitch, float radius );
+void HeadingPitchRadiusFromVec3( sgVec3 hpr, sgVec3 vec3 );
//void PilotOffsetGet( float *po );
sgVec3 *PilotOffsetGet();
void PilotOffsetSet( int opt, float setting);
/* binding functions for chase view offset */
static void
-setPilotOffsetHeadingDeg (float value)
+setPilotXOffset (float value)
{
PilotOffsetSet(0, value);
}
static float
-getPilotOffsetHeadingDeg ()
+getPilotXOffset ()
{
return( PilotOffsetGetSetting(0) );
}
static void
-setPilotOffsetPitchDeg (float value)
+setPilotYOffset (float value)
{
PilotOffsetSet(1, value);
}
static float
-getPilotOffsetPitchDeg ()
+getPilotYOffset ()
{
return( PilotOffsetGetSetting(1) );
}
static void
-setPilotOffsetRadiusM (float value)
+setPilotZOffset (float value)
{
PilotOffsetSet(2, value);
}
static float
-getPilotOffsetRadiusM ()
+getPilotZOffset ()
{
return( PilotOffsetGetSetting(2) );
}
-
= fgGetNode("/position/latitude-deg");
static const SGPropertyNode *altitude
= fgGetNode("/position/altitude-ft");
+ static const SGPropertyNode *groundlevel_nearplane
+ = fgGetNode("/sim/current-view/ground-level-nearplane-m");
// Update the default (kludged) properties.
fgUpdateProps();
double agl = current_aircraft.fdm_state->get_Altitude() * SG_FEET_TO_METER
- scenery.get_cur_elev();
-// if (fgGetBool("/sim/view/internal"))
-// ssgSetNearFar( 0.2f, 120000.0f );
-// else if ( agl > 10.0)
-
if ( agl > 10.0 ) {
scene_nearplane = 10.0f;
scene_farplane = 120000.0f;
} else {
- scene_nearplane = 0.5f;
+ scene_nearplane = groundlevel_nearplane->getDoubleValue();
scene_farplane = 120000.0f;
}
fgSetInt("/sim/startup/ysize", 600);
fgSetInt("/sim/rendering/bits-per-pixel", 16);
fgSetString("/sim/view-mode", "pilot");
- fgSetDouble("/sim/view/offset-deg", 0);
+ fgSetDouble("/sim/current-view/heading-offset-deg", 0);
fgSetDouble("/environment/visibility-m", 20000);
// HUD options
if ( fov < FG_FOV_MIN ) { fov = FG_FOV_MIN; }
if ( fov > FG_FOV_MAX ) { fov = FG_FOV_MAX; }
- fgSetDouble("/sim/field-of-view", fov);
+ fgSetDouble("/sim/current-view/field-of-view", fov);
// printf("parse_fov(): result = %.4f\n", fov);
(FGViewer *)globals->get_viewmgr()->get_view( 0 );
pilot_view->setHeadingOffset_deg( default_view_offset * SGD_RADIANS_TO_DEGREES );
pilot_view->setGoalHeadingOffset_deg( default_view_offset * SGD_RADIANS_TO_DEGREES );
- fgSetDouble("/sim/view/offset-deg", default_view_offset * SGD_RADIANS_TO_DEGREES );
+ fgSetDouble( "/sim/current-view/heading-offset-deg",
+ default_view_offset * SGD_RADIANS_TO_DEGREES );
// $$$ end - added VS Renganathan, 14 Oct 2K
} else if ( arg.find( "--visibility=" ) == 0 ) {
fgSetDouble("/environment/visibility-m", atof(arg.substr(13)));
<< " instances allowed." << endl
<< endl;
}
-
-
-
// Norman's Optimized matrix rotators! //
//////////////////////////////////////////////////////////////////
-static void fgMakeLOCAL( sgMat4 dst, const double Theta,
- const double Phi, const double Psi)
-{
- SGfloat cosTheta = (SGfloat) cos(Theta);
- SGfloat sinTheta = (SGfloat) sin(Theta);
- SGfloat cosPhi = (SGfloat) cos(Phi);
- SGfloat sinPhi = (SGfloat) sin(Phi);
- SGfloat sinPsi = (SGfloat) sin(Psi) ;
- SGfloat cosPsi = (SGfloat) cos(Psi) ;
-
- dst[0][0] = cosPhi * cosTheta;
- dst[0][1] = sinPhi * cosPsi + cosPhi * -sinTheta * -sinPsi;
- dst[0][2] = sinPhi * sinPsi + cosPhi * -sinTheta * cosPsi;
- dst[0][3] = SG_ZERO;
-
- dst[1][0] = -sinPhi * cosTheta;
- dst[1][1] = cosPhi * cosPsi + -sinPhi * -sinTheta * -sinPsi;
- dst[1][2] = cosPhi * sinPsi + -sinPhi * -sinTheta * cosPsi;
- dst[1][3] = SG_ZERO ;
-
- dst[2][0] = sinTheta;
- dst[2][1] = cosTheta * -sinPsi;
- dst[2][2] = cosTheta * cosPsi;
- dst[2][3] = SG_ZERO;
-
- dst[3][0] = SG_ZERO;
- dst[3][1] = SG_ZERO;
- dst[3][2] = SG_ZERO;
- dst[3][3] = SG_ONE ;
-}
-
// Since these are pure rotation matrices we can save some bookwork
// by considering them to be 3x3 until the very end -- NHV
dst[3][3] = SG_ONE;
}
-// Taking advantage of the 3x3 nature of this -- NHV
-inline static void MakeWithWorldUp( sgMat4 dst, const sgMat4 UP, const sgMat4 LOCAL )
-{
- sgMat4 tmp;
-
- float a = UP[0][0];
- float b = UP[1][0];
- float c = UP[2][0];
- tmp[0][0] = a*LOCAL[0][0] + b*LOCAL[0][1] + c*LOCAL[0][2] ;
- tmp[1][0] = a*LOCAL[1][0] + b*LOCAL[1][1] + c*LOCAL[1][2] ;
- tmp[2][0] = a*LOCAL[2][0] + b*LOCAL[2][1] + c*LOCAL[2][2] ;
- tmp[3][0] = SG_ZERO ;
-
- a = UP[0][1];
- b = UP[1][1];
- c = UP[2][1];
- tmp[0][1] = a*LOCAL[0][0] + b*LOCAL[0][1] + c*LOCAL[0][2] ;
- tmp[1][1] = a*LOCAL[1][0] + b*LOCAL[1][1] + c*LOCAL[1][2] ;
- tmp[2][1] = a*LOCAL[2][0] + b*LOCAL[2][1] + c*LOCAL[2][2] ;
- tmp[3][1] = SG_ZERO ;
-
- a = UP[0][2];
- c = UP[2][2];
- tmp[0][2] = a*LOCAL[0][0] + c*LOCAL[0][2] ;
- tmp[1][2] = a*LOCAL[1][0] + c*LOCAL[1][2] ;
- tmp[2][2] = a*LOCAL[2][0] + c*LOCAL[2][2] ;
- tmp[3][2] = SG_ZERO ;
-
- tmp[0][3] = SG_ZERO ;
- tmp[1][3] = SG_ZERO ;
- tmp[2][3] = SG_ZERO ;
- tmp[3][3] = SG_ONE ;
- sgCopyMat4(dst, tmp);
-}
-
////////////////////////////////////////////////////////////////////////
// Implementation of FGViewer.
////////////////////////////////////////////////////////////////////////
// Constructor
-FGViewer::FGViewer( fgViewType Type, bool from_model, int from_model_index, bool at_model, int at_model_index ):
+FGViewer::FGViewer( fgViewType Type, bool from_model, int from_model_index, bool at_model, int at_model_index, double x_offset_m, double y_offset_m, double z_offset_m, double near_m ):
_scaling_type(FG_SCALING_MAX),
_fov_deg(55.0),
_dirty(true),
_roll_deg(0),
_pitch_deg(0),
_heading_deg(0),
- _x_offset_m(0),
- _y_offset_m(0),
- _z_offset_m(0),
_heading_offset_deg(0),
_pitch_offset_deg(0),
_roll_offset_deg(0),
_from_model_index = from_model_index;
_at_model = at_model;
_at_model_index = at_model_index;
+ _x_offset_m = x_offset_m;
+ _y_offset_m = y_offset_m;
+ _z_offset_m = z_offset_m;
+ _ground_level_nearplane_m = near_m;
//a reasonable guess for init, so that the math doesn't blow up
}
sgVec3 minus_z, right, forward, tilt;
sgMat4 tmpROT; // temp rotation work matrices
sgVec3 eye_pos, at_pos;
+ sgVec3 position_offset; // eye position offsets (xyz)
// The position vectors originate from the view point or target location
// depending on the type of view.
sgSetVec3( right, LOCAL[1][0], LOCAL[1][1], LOCAL[1][2] );
sgSetVec3( forward, -LOCAL[0][0], -LOCAL[0][1], -LOCAL[0][2] );
- // create the (xyz) eye Position offsets Vector
- sgVec3 position_offset;
- sgSetVec3( position_offset, -_z_offset_m, _x_offset_m, _y_offset_m );
-
-
if (_type == FG_LOOKAT) {
// Note that when in "lookat" view the "world up" vector is always applied
(_heading_offset_deg -_heading_deg) * SG_DEGREES_TO_RADIANS, _world_up,
_pitch_offset_deg * SG_DEGREES_TO_RADIANS, right );
- // Eye Position Offsets to vector
- sgXformVec3( position_offset, position_offset, UP );
-
// add in the Orientation Offsets here
+ sgSetVec3( position_offset, _x_offset_m, _y_offset_m, _z_offset_m );
+ sgXformVec3( position_offset, position_offset, UP);
+
sgXformVec3( position_offset, position_offset, VIEW_OFFSET );
// add the Position offsets from object to the eye position
_heading_offset_deg * SG_DEGREES_TO_RADIANS, _view_up,
_pitch_offset_deg * SG_DEGREES_TO_RADIANS, right );
- // Eye Position Offsets to vector
- sgXformVec3( position_offset, position_offset, LOCAL);
-
- // add the offsets including rotations to the translation vector
- sgAddVec3( _view_pos, position_offset );
-
// Make the VIEW matrix.
sgSetVec4(VIEW[0], right[0], right[1], right[2],SG_ZERO);
sgSetVec4(VIEW[1], forward[0], forward[1], forward[2],SG_ZERO);
sgSetVec4(VIEW[2], _view_up[0], _view_up[1], _view_up[2],SG_ZERO);
sgSetVec4(VIEW[3], SG_ZERO, SG_ZERO, SG_ZERO,SG_ONE);
+
+ // rotate matrix to get a matrix to apply Eye Position Offsets
+ sgMat4 VIEW_UP; // L0 forward L1 right L2 up
+ sgCopyVec4(VIEW_UP[0], LOCAL[1]);
+ sgCopyVec4(VIEW_UP[1], LOCAL[2]);
+ sgCopyVec4(VIEW_UP[2], LOCAL[0]);
+ sgZeroVec4(VIEW_UP[3]);
+
+ // Eye Position Offsets to vector
+ sgSetVec3( position_offset, _x_offset_m, _y_offset_m, _z_offset_m );
+ sgXformVec3( position_offset, position_offset, VIEW_UP);
+
+ // add the offsets including rotations to the translation vector
+ sgAddVec3( _view_pos, position_offset );
+
// multiply the OFFSETS (for heading and pitch) into the VIEW
sgPostMultMat4(VIEW, VIEW_OFFSET);
}
}
}
-
-
-
-
-
-
-
};
// Constructor
- FGViewer( fgViewType Type, bool from_model, int from_model_index, bool at_model, int at_model_index );
+ FGViewer( fgViewType Type, bool from_model, int from_model_index,
+ bool at_model, int at_model_index, double x_offset_m,
+ double y_offset_m, double z_offset_m, double near_m );
// Destructor
virtual ~FGViewer( void );
virtual const sgVec4 *get_UP() { if ( _dirty ) { recalc(); } return UP; }
//////////////////////////////////////////////////////////////////////
- // Part 4: frustrum data setters and getters
+ // Part 4: View and frustrum data setters and getters
//////////////////////////////////////////////////////////////////////
virtual void set_fov( double fov_deg ) {
}
virtual double get_aspect_ratio() const { return _aspect_ratio; }
+ 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
//////////////////////////////////////////////////////////////////////
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;
bool at_model = false;
int from_model_index = 0;
int at_model_index = 0;
+ double x_offset_m, y_offset_m, z_offset_m;
+ double near_m;
for (int i = 0; i < fgGetInt("/sim/number-views"); i++) {
viewpath = "/sim/view";
}
}
+ nodepath = viewpath;
+ nodepath += "/config/x-offset-m";
+ x_offset_m = fgGetDouble(nodepath.c_str());
+ nodepath = viewpath;
+ nodepath += "/config/y-offset-m";
+ y_offset_m = fgGetDouble(nodepath.c_str());
+ nodepath = viewpath;
+ nodepath += "/config/z-offset-m";
+ z_offset_m = fgGetDouble(nodepath.c_str());
+
+ nodepath = viewpath;
+ nodepath += "/config/ground-level-nearplane-m";
+ near_m = fgGetDouble(nodepath.c_str());
+
// supporting two types now "lookat" = 1 and "lookfrom" = 0
if ( strcmp("lookat",strdata.c_str()) == 0 )
- add_view(new FGViewer ( FG_LOOKAT, from_model, from_model_index, at_model, at_model_index ));
+ add_view(new FGViewer ( FG_LOOKAT, from_model, from_model_index,
+ at_model, at_model_index, x_offset_m, y_offset_m,
+ z_offset_m, near_m ));
else
- add_view(new FGViewer ( FG_LOOKFROM, from_model, from_model_index, false, 0 ));
+ add_view(new FGViewer ( FG_LOOKFROM, from_model, from_model_index, false,
+ 0, x_offset_m, y_offset_m, z_offset_m, near_m ));
+
}
+
+ copyToCurrent();
+
}
typedef double (FGViewMgr::*double_getter)() const;
void
FGViewMgr::bind ()
{
- // FIXME:
- // need to redo these bindings to the new locations (move to viewer?)
- fgTie("/sim/view/offset-deg", this,
+ // these are bound to the current view properties
+ fgTie("/sim/current-view/heading-offset-deg", this,
&FGViewMgr::getViewOffset_deg, &FGViewMgr::setViewOffset_deg);
- fgSetArchivable("/sim/view/offset-deg");
- fgTie("/sim/view/goal-offset-deg", this,
+ fgSetArchivable("/sim/current-view/heading-offset-deg");
+ fgTie("/sim/current-view/goal-heading-offset-deg", this,
&FGViewMgr::getGoalViewOffset_deg, &FGViewMgr::setGoalViewOffset_deg);
- fgSetArchivable("/sim/view/goal-offset-deg");
- fgTie("/sim/view/tilt-deg", this,
+ fgSetArchivable("/sim/current-view/goal-heading-offset-deg");
+ fgTie("/sim/current-view/pitch-offset-deg", this,
&FGViewMgr::getViewTilt_deg, &FGViewMgr::setViewTilt_deg);
- fgSetArchivable("/sim/view/tilt-deg");
- fgTie("/sim/view/goal-tilt-deg", this,
+ fgSetArchivable("/sim/current-view/pitch-offset-deg");
+ fgTie("/sim/current-view/goal-pitch-offset-deg", this,
&FGViewMgr::getGoalViewTilt_deg, &FGViewMgr::setGoalViewTilt_deg);
- fgSetArchivable("/sim/view/goal-tilt-deg");
- fgTie("/sim/view/pilot/x-offset-m", this,
- &FGViewMgr::getPilotXOffset_m, &FGViewMgr::setPilotXOffset_m);
- fgSetArchivable("/sim/view/pilot/x-offset-m");
- fgTie("/sim/view/pilot/y-offset-m", this,
- &FGViewMgr::getPilotYOffset_m, &FGViewMgr::setPilotYOffset_m);
- fgSetArchivable("/sim/view/pilot/y-offset-m");
- fgTie("/sim/view/pilot/z-offset-m", this,
- &FGViewMgr::getPilotZOffset_m, &FGViewMgr::setPilotZOffset_m);
- fgSetArchivable("/sim/view/pilot/z-offset-m");
- fgTie("/sim/field-of-view", this,
- &FGViewMgr::getFOV_deg, &FGViewMgr::setFOV_deg);
- fgSetArchivable("/sim/field-of-view");
- fgTie("/sim/view/axes/long", this,
+ fgSetArchivable("/sim/current-view/goal-pitch-offset-deg");
+
+ fgTie("/sim/current-view/axes/long", this,
(double_getter)0, &FGViewMgr::setViewAxisLong);
- fgTie("/sim/view/axes/lat", this,
+ fgTie("/sim/current-view/axes/lat", this,
(double_getter)0, &FGViewMgr::setViewAxisLat);
+
+ fgTie("/sim/current-view/field-of-view", this,
+ &FGViewMgr::getFOV_deg, &FGViewMgr::setFOV_deg);
+ fgSetArchivable("/sim/current-view/field-of-view");
+
+ fgTie("/sim/current-view/ground-level-nearplane-m", this,
+ &FGViewMgr::getNear_m, &FGViewMgr::setNear_m);
+ fgSetArchivable("/sim/current-view/ground-level-nearplane-m");
+
}
void
{
// FIXME:
// need to redo these bindings to the new locations (move to viewer?)
- fgUntie("/sim/view/offset-deg");
- fgUntie("/sim/view/goal-offset-deg");
- fgUntie("/sim/view/tilt-deg");
- fgUntie("/sim/view/goal-tilt-deg");
- fgUntie("/sim/view/pilot/x-offset-m");
- fgUntie("/sim/view/pilot/y-offset-m");
- fgUntie("/sim/view/pilot/z-offset-m");
+ fgUntie("/sim/current-view/heading-offset-deg");
+ fgUntie("/sim/current-view/goal-heading-offset-deg");
+ fgUntie("/sim/current-view/pitch-offset-deg");
+ fgUntie("/sim/current-view/goal-pitch-offset-deg");
fgUntie("/sim/field-of-view");
- fgUntie("/sim/view/axes/long");
- fgUntie("/sim/view/axes/lat");
+ fgUntie("/sim/current-view/axes/long");
+ fgUntie("/sim/current-view/axes/lat");
}
void
loop_view->set_dirty();
}
}
+ setPilotXOffset_m(fgGetDouble("/sim/current-view/x-offset-m"));
+ setPilotYOffset_m(fgGetDouble("/sim/current-view/y-offset-m"));
+ setPilotZOffset_m(fgGetDouble("/sim/current-view/z-offset-m"));
- // Set up the chase view
- // FIXME:
- // Gotta change sgVec3Slider so that it takes xyz values as inputs
- // instead of spherical coordinates.
- FGViewer *chase_view = (FGViewer *)get_view( 1 );
-
- // get xyz Position offsets directly from GUI/sgVec3Slider
- // FIXME: change GUI/sgVec3Slider to store the xyz in properties
- // it would probably be faster than the way PilotOffsetGet()
- // triggers a recalc all the time.
- sgVec3 *pPO = PilotOffsetGet();
- sgVec3 zPO;
- sgCopyVec3( zPO, *pPO );
- chase_view->setPositionOffsets(zPO[1], zPO[2], zPO[0] );
-
- // Update the current view
+ // Update the current view
do_axes();
view->update(dt);
+ double tmp;
}
+void
+FGViewMgr::copyToCurrent()
+{
+ fgSetDouble("/sim/current-view/x-offset-m", getPilotXOffset_m());
+ fgSetDouble("/sim/current-view/y-offset-m", getPilotYOffset_m());
+ fgSetDouble("/sim/current-view/z-offset-m", getPilotZOffset_m());
+}
+
+
double
FGViewMgr::getViewOffset_deg () const
{
double
FGViewMgr::getPilotXOffset_m () const
{
- // FIXME: hard-coded pilot view position
- const FGViewer * pilot_view = get_view(0);
- if (pilot_view != 0) {
- return ((FGViewer *)pilot_view)->getXOffset_m();
+ const FGViewer * view = get_current_view();
+ if (view != 0) {
+ return ((FGViewer *)view)->getXOffset_m();
} else {
return 0;
}
void
FGViewMgr::setPilotXOffset_m (double x)
{
- // FIXME: hard-coded pilot view position
- FGViewer * pilot_view = get_view(0);
- if (pilot_view != 0) {
- pilot_view->setXOffset_m(x);
+ FGViewer * view = get_current_view();
+ if (view != 0) {
+ view->setXOffset_m(x);
}
}
double
FGViewMgr::getPilotYOffset_m () const
{
- // FIXME: hard-coded pilot view position
- const FGViewer * pilot_view = get_view(0);
- if (pilot_view != 0) {
- return ((FGViewer *)pilot_view)->getYOffset_m();
+ const FGViewer * view = get_current_view();
+ if (view != 0) {
+ return ((FGViewer *)view)->getYOffset_m();
} else {
return 0;
}
void
FGViewMgr::setPilotYOffset_m (double y)
{
- // FIXME: hard-coded pilot view position
- FGViewer * pilot_view = get_view(0);
- if (pilot_view != 0) {
- pilot_view->setYOffset_m(y);
+ FGViewer * view = get_current_view();
+ if (view != 0) {
+ view->setYOffset_m(y);
}
}
double
FGViewMgr::getPilotZOffset_m () const
{
- // FIXME: hard-coded pilot view position
- const FGViewer * pilot_view = get_view(0);
- if (pilot_view != 0) {
- return ((FGViewer *)pilot_view)->getZOffset_m();
+ const FGViewer * view = get_current_view();
+ if (view != 0) {
+ return ((FGViewer *)view)->getZOffset_m();
} else {
return 0;
}
void
FGViewMgr::setPilotZOffset_m (double z)
{
- // FIXME: hard-coded pilot view position
- FGViewer * pilot_view = get_view(0);
- if (pilot_view != 0) {
- pilot_view->setZOffset_m(z);
+ FGViewer * view = get_current_view();
+ if (view != 0) {
+ view->setZOffset_m(z);
}
}
view->set_fov(fov);
}
+double
+FGViewMgr::getNear_m () const
+{
+ const FGViewer * view = get_current_view();
+ return (view == 0 ? 0.5f : view->getNear_m());
+}
+
+void
+FGViewMgr::setNear_m (double near_m)
+{
+ FGViewer * view = get_current_view();
+ if (view != 0)
+ view->setNear_m(near_m);
+}
+
void
FGViewMgr::setViewAxisLong (double axis)
{
get_current_view()->setGoalHeadingOffset_deg(viewDir);
}
-
if ( current >= (int)views.size() ) {
current = 0;
}
+ copyToCurrent();
return views[current];
}
inline FGViewer *prev_view() {
void setPilotZOffset_m (double z);
double getFOV_deg () const;
void setFOV_deg (double fov);
+ double getNear_m () const;
+ void setNear_m (double near_m);
void setViewAxisLong (double axis);
void setViewAxisLat (double axis);
+ void copyToCurrent ();
typedef vector < FGViewer * > viewer_list;
viewer_list views;