From 71598c12f80b47ea02973d2deb0b48bbe5e85b3f Mon Sep 17 00:00:00 2001 From: curt Date: Thu, 18 Apr 2002 16:51:47 +0000 Subject: [PATCH] Jim Wilson: These are the updates for the View manager properties. Removed the last of items (within the viewer/viewmgr) hard coded to view number. Added support for per view configuration of ground level nearplane value. Tower views look very nice with little or no z-buffer problem in the models. Pilot offset dialog can be used to move eye in all views. --- src/GUI/gui.cxx | 7 +- src/GUI/sgVec3Slider.cxx | 207 +++++++++++++++++++++++++++++++-------- src/GUI/sgVec3Slider.hxx | 14 +-- src/Main/main.cxx | 8 +- src/Main/options.cxx | 10 +- src/Main/viewer.cxx | 115 +++++----------------- src/Main/viewer.hxx | 14 ++- src/Main/viewmgr.cxx | 175 +++++++++++++++++++-------------- src/Main/viewmgr.hxx | 4 + 9 files changed, 322 insertions(+), 232 deletions(-) diff --git a/src/GUI/gui.cxx b/src/GUI/gui.cxx index 019df4bfc..5d9f2ca00 100644 --- a/src/GUI/gui.cxx +++ b/src/GUI/gui.cxx @@ -690,10 +690,10 @@ static GlBitmap *b1 = NULL; 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"); @@ -712,7 +712,7 @@ GLubyte *hiResScreenCapture( int multiplier ) 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 @@ -1064,4 +1064,3 @@ void guiInit() guiToggleMenu(); // Menu off by default } } - diff --git a/src/GUI/sgVec3Slider.cxx b/src/GUI/sgVec3Slider.cxx index 3ef12ba16..4c1b469e7 100644 --- a/src/GUI/sgVec3Slider.cxx +++ b/src/GUI/sgVec3Slider.cxx @@ -35,9 +35,9 @@ public: float max = 100.0f, float min = 0.0f); ~FloatSlider () {;} - - static void adj( puObject *); + static void adj( puObject *); + void updateText() { sprintf( _text, "%05.2f", MyValue ); } @@ -52,6 +52,9 @@ public: // 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; @@ -69,7 +72,7 @@ public: void FloatSlider::adj( puObject *hs ) { - FloatSlider *slider = (FloatSlider *)hs->getUserData(); + FloatSlider *slider = (FloatSlider *)hs; slider->getValue ( slider->getTmp() ); slider->setTmp(); slider->set(); @@ -79,17 +82,15 @@ void FloatSlider::adj( puObject *hs ) 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 ); } @@ -131,6 +132,9 @@ public: // 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 @@ -150,7 +154,7 @@ public: void FloatDial::adj( puObject *hs ) { - FloatDial *dial = (FloatDial *)hs->getUserData(); + FloatDial *dial = (FloatDial *)hs; dial->getValue ( dial->getTmp() ); dial->setTmp(); dial->set(); @@ -160,14 +164,12 @@ void FloatDial::adj( puObject *hs ) 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 ); @@ -180,6 +182,10 @@ FloatDial::FloatDial ( int x, int y, int sz, float f, const char *title, 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); @@ -193,6 +199,8 @@ protected: puOneShot *OkButton; puOneShot *ResetButton; puOneShot *CancelButton; + puArrowButton *right_arrow; + puArrowButton *left_arrow; sgVec3 Vec, SaveVec; public: @@ -201,10 +209,11 @@ 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() { @@ -238,16 +247,19 @@ public: }; // 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)); @@ -284,12 +296,26 @@ sgVec3Slider::sgVec3Slider ( int x, int y, sgVec3 vec, const char *title, /* 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"); @@ -305,14 +331,49 @@ sgVec3Slider::sgVec3Slider ( int x, int y, sgVec3 vec, const char *title, 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(); @@ -343,6 +404,23 @@ void sgVec3Slider::cancel(puObject *p_obj) 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()); @@ -360,30 +438,25 @@ void sgVec3SliderAdjust( puObject *p_obj ) 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); } } @@ -393,8 +466,8 @@ void PilotOffsetAdjust( puObject * ) PilotOffsetInit(); } sgVec3Slider *me = (sgVec3Slider *)PO_vec -> getUserData(); - me -> stashVec(); me -> adjust( me ); + me -> stashVec(); FG_PUSH_PUI_DIALOG( me ); } @@ -416,9 +489,11 @@ float PilotOffsetGetSetting(int opt) 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 ); } @@ -429,9 +504,18 @@ void PilotOffsetSet(int opt, float 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(); } @@ -440,7 +524,7 @@ void PilotOffsetSet(int opt, float setting) // 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 ) { @@ -475,3 +559,44 @@ 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]; + } + } + } +} diff --git a/src/GUI/sgVec3Slider.hxx b/src/GUI/sgVec3Slider.hxx index 448b830d1..8772dc6cc 100644 --- a/src/GUI/sgVec3Slider.hxx +++ b/src/GUI/sgVec3Slider.hxx @@ -18,6 +18,7 @@ void PilotOffsetInit(); 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); @@ -28,40 +29,39 @@ float PilotOffsetGetSetting( int opt ); /* 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) ); } - diff --git a/src/Main/main.cxx b/src/Main/main.cxx index 69292a3c2..2dcc30f77 100644 --- a/src/Main/main.cxx +++ b/src/Main/main.cxx @@ -407,6 +407,8 @@ void fgRenderFrame( void ) { = 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(); @@ -592,15 +594,11 @@ void fgRenderFrame( void ) { 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; } diff --git a/src/Main/options.cxx b/src/Main/options.cxx index e6257c4a5..4f37eeb63 100644 --- a/src/Main/options.cxx +++ b/src/Main/options.cxx @@ -177,7 +177,7 @@ fgSetDefaults () 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 @@ -427,7 +427,7 @@ parse_fov( const string& arg ) { 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); @@ -886,7 +886,8 @@ parse_option (const string& arg) (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))); @@ -1290,6 +1291,3 @@ fgUsage () << " instances allowed." << endl << endl; } - - - diff --git a/src/Main/viewer.cxx b/src/Main/viewer.cxx index 2c3fde746..f28a4dad8 100644 --- a/src/Main/viewer.cxx +++ b/src/Main/viewer.cxx @@ -52,37 +52,6 @@ // 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 @@ -156,48 +125,13 @@ static void MakeVIEW_OFFSET( sgMat4 dst, 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), @@ -210,9 +144,6 @@ FGViewer::FGViewer( fgViewType Type, bool from_model, int from_model_index, bool _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), @@ -225,6 +156,10 @@ FGViewer::FGViewer( fgViewType Type, bool from_model, int from_model_index, bool _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 } @@ -551,6 +486,7 @@ FGViewer::recalc () 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. @@ -628,11 +564,6 @@ FGViewer::recalc () 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 @@ -644,10 +575,10 @@ FGViewer::recalc () (_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 @@ -671,17 +602,26 @@ FGViewer::recalc () _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); @@ -832,10 +772,3 @@ FGViewer::update (int dt) } } } - - - - - - - diff --git a/src/Main/viewer.hxx b/src/Main/viewer.hxx index ce3216450..0fc7125d9 100644 --- a/src/Main/viewer.hxx +++ b/src/Main/viewer.hxx @@ -62,7 +62,9 @@ public: }; // 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 ); @@ -216,7 +218,7 @@ public: 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 ) { @@ -231,6 +233,11 @@ public: } 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 ////////////////////////////////////////////////////////////////////// @@ -281,6 +288,9 @@ private: 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; diff --git a/src/Main/viewmgr.cxx b/src/Main/viewmgr.cxx index 971480647..56bd8ed54 100644 --- a/src/Main/viewmgr.cxx +++ b/src/Main/viewmgr.cxx @@ -54,6 +54,8 @@ FGViewMgr::init () 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"; @@ -94,12 +96,33 @@ FGViewMgr::init () } } + 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; @@ -107,36 +130,33 @@ 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 @@ -144,16 +164,13 @@ FGViewMgr::unbind () { // 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 @@ -235,27 +252,25 @@ FGViewMgr::update (int dt) 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 { @@ -323,10 +338,9 @@ FGViewMgr::setGoalViewTilt_deg (double tilt) 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; } @@ -335,20 +349,18 @@ FGViewMgr::getPilotXOffset_m () const 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; } @@ -357,20 +369,18 @@ FGViewMgr::getPilotYOffset_m () const 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; } @@ -379,10 +389,9 @@ FGViewMgr::getPilotZOffset_m () const 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); } } @@ -401,6 +410,21 @@ FGViewMgr::setFOV_deg (double fov) 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) { @@ -456,4 +480,3 @@ FGViewMgr::do_axes () get_current_view()->setGoalHeadingOffset_deg(viewDir); } - diff --git a/src/Main/viewmgr.hxx b/src/Main/viewmgr.hxx index e1dcff32b..6101f2aef 100644 --- a/src/Main/viewmgr.hxx +++ b/src/Main/viewmgr.hxx @@ -93,6 +93,7 @@ public: if ( current >= (int)views.size() ) { current = 0; } + copyToCurrent(); return views[current]; } inline FGViewer *prev_view() { @@ -134,8 +135,11 @@ private: 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; -- 2.39.5