From: James Turner Date: Mon, 13 Jun 2011 21:34:00 +0000 (+0100) Subject: Expose departure+arrival airport + runway on route-manager. X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=af6ed2ff3a0e8b04b42e1992e5d79c3156b7b358;p=flightgear.git Expose departure+arrival airport + runway on route-manager. --- diff --git a/src/Autopilot/route_mgr.cxx b/src/Autopilot/route_mgr.cxx index 94ec9980e..f9bd77091 100644 --- a/src/Autopilot/route_mgr.cxx +++ b/src/Autopilot/route_mgr.cxx @@ -1556,3 +1556,42 @@ void FGRouteMgr::setDestinationICAO(const char* aIdent) arrivalChanged(); } + +FGAirportRef FGRouteMgr::departureAirport() const +{ + return _departure; +} + +FGAirportRef FGRouteMgr::destinationAirport() const +{ + return _destination; +} + +FGRunway* FGRouteMgr::departureRunway() const +{ + if (!_departure) { + return NULL; + } + + string runwayId(departure->getStringValue("runway")); + if (!_departure->hasRunwayWithIdent(runwayId)) { + return NULL; + } + + return _departure->getRunwayByIdent(runwayId); +} + +FGRunway* FGRouteMgr::destinationRunway() const +{ + if (!_destination) { + return NULL; + } + + string runwayId(destination->getStringValue("runway")); + if (!_destination->hasRunwayWithIdent(runwayId)) { + return NULL; + } + + return _destination->getRunwayByIdent(runwayId); +} + diff --git a/src/Autopilot/route_mgr.hxx b/src/Autopilot/route_mgr.hxx index 31336f96a..a309bb364 100644 --- a/src/Autopilot/route_mgr.hxx +++ b/src/Autopilot/route_mgr.hxx @@ -35,6 +35,8 @@ class SGPath; class PropertyWatcher; class FGAirport; +class FGRunway; + typedef SGSharedPtr FGAirportRef; /** @@ -134,6 +136,12 @@ public: * - navaid/radial-deg/offset-nm */ flightgear::WayptRef waypointFromString(const std::string& target); + + FGAirportRef departureAirport() const; + FGAirportRef destinationAirport() const; + + FGRunway* departureRunway() const; + FGRunway* destinationRunway() const; private: flightgear::WayptVec _route; int _currentIndex; diff --git a/src/Instrumentation/NavDisplay.cxx b/src/Instrumentation/NavDisplay.cxx index 3d0e401b7..c5d573f08 100644 --- a/src/Instrumentation/NavDisplay.cxx +++ b/src/Instrumentation/NavDisplay.cxx @@ -31,10 +31,7 @@ #include #include #include - #include -#include -#include #include #include @@ -70,26 +67,18 @@ using std::endl; #include "instrument_mgr.hxx" #include "od_gauge.hxx" -static const float UNIT = 1.0f / 8.0f; // 8 symbols in a row/column in the texture +static const int SYMBOL_TEX_DIM = 8; +static const float UNIT = 1.0 / SYMBOL_TEX_DIM; static const char *DEFAULT_FONT = "typewriter.txf"; NavDisplay::NavDisplay(SGPropertyNode *node) : _name(node->getStringValue("name", "nd")), _num(node->getIntValue("number", 0)), _time(0.0), - _interval(node->getDoubleValue("update-interval-sec", 1.0)), - _elapsed_time(0), - _persistance(0), - _sim_init_done(false), + _updateInterval(node->getDoubleValue("update-interval-sec", 0.1)), _odg(0), _scale(0), - _angle_offset(0), _view_heading(0), - _x_offset(0), - _y_offset(0), - _radar_ref_rng(0), - _lat(0), - _lon(0), _resultTexture(0), _font_size(0), _font_spacing(0), @@ -150,21 +139,28 @@ NavDisplay::init () _radar_centre_node = n->getNode("centre", true); _radar_tcas_node = n->getNode("tcas", true); _radar_absalt_node = n->getNode("abs-altitude", true); - + _radar_arpt_node = n->getNode("airport", true); + _radar_station_node = n->getNode("station", true); + _draw_track_node = n->getNode("ground-track", true); + _draw_heading_node = n->getNode("heading", true); + _draw_north_node = n->getNode("north", true); + _draw_fix_node = n->getNode("fixes", true); + _ai_enabled_node = fgGetNode("/sim/ai/enabled", true); _route = static_cast(globals->get_subsystem("route-manager")); + _navRadio1Node = fgGetNode("/instrumentation/nav[0]", true); + _navRadio2Node = fgGetNode("/instrumentation/nav[1]", true); + // OSG geometry setup _radarGeode = new osg::Geode; - osg::StateSet *stateSet = _radarGeode->getOrCreateStateSet(); - stateSet->setTextureAttributeAndModes(0, _symbols.get()); - - osg::LineWidth *lw = new osg::LineWidth(); - lw->setWidth(2.0); - stateSet->setAttribute(lw); - + _geom = new osg::Geometry; _geom->setUseDisplayList(false); + + osg::StateSet *stateSet = _geom->getOrCreateStateSet(); + stateSet->setTextureAttributeAndModes(0, _symbols.get()); + // Initially allocate space for 128 quads _vertices = new osg::Vec2Array; _vertices->setDataVariance(osg::Object::DYNAMIC); @@ -175,10 +171,9 @@ NavDisplay::init () _texCoords->reserve(128 * 4); _geom->setTexCoordArray(0, _texCoords); - osg::Vec3Array *colors = new osg::Vec3Array; - colors->push_back(osg::Vec3(1.0f, 1.0f, 1.0f)); // color of echos - _geom->setColorBinding(osg::Geometry::BIND_PER_PRIMITIVE_SET); - _geom->setColorArray(colors); + _quadColors = new osg::Vec3Array; + _geom->setColorBinding(osg::Geometry::BIND_PER_VERTEX); + _geom->setColorArray(_quadColors); _symbolPrimSet = new osg::DrawArrays(osg::PrimitiveSet::QUADS); _symbolPrimSet->setDataVariance(osg::Object::DYNAMIC); @@ -193,17 +188,21 @@ NavDisplay::init () _lineGeometry = new osg::Geometry; _lineGeometry->setUseDisplayList(false); + stateSet = _lineGeometry->getOrCreateStateSet(); + osg::LineWidth *lw = new osg::LineWidth(); + lw->setWidth(2.0); + stateSet->setAttribute(lw); _lineVertices = new osg::Vec2Array; _lineVertices->setDataVariance(osg::Object::DYNAMIC); _lineVertices->reserve(128 * 4); - _lineGeometry->setVertexArray(_vertices); + _lineGeometry->setVertexArray(_lineVertices); _lineColors = new osg::Vec3Array; _lineColors->setDataVariance(osg::Object::DYNAMIC); _lineGeometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX); - _lineGeometry->setColorArray(colors); + _lineGeometry->setColorArray(_lineColors); _linePrimSet = new osg::DrawArrays(osg::PrimitiveSet::LINES); _linePrimSet->setDataVariance(osg::Object::DYNAMIC); @@ -219,7 +218,10 @@ NavDisplay::init () osg::Camera *camera = _odg->getCamera(); camera->addChild(_radarGeode.get()); camera->addChild(_textGeode.get()); - + osg::Texture2D* tex = _odg->getTexture(); + camera->setProjectionMatrixAsOrtho2D(0, tex->getTextureWidth(), + 0, tex->getTextureHeight()); + updateFont(); } @@ -237,19 +239,6 @@ const osg::Vec2f symbolTexCoords[4] = { }; -// helper -static void -addQuad(osg::Vec2Array *vertices, osg::Vec2Array *texCoords, - const osg::Matrixf& transform, const osg::Vec2f& texBase) -{ - for (int i = 0; i < 4; i++) { - const osg::Vec3f coords = transform.preMult(symbolCoords[i]); - texCoords->push_back(texBase + symbolTexCoords[i]); - vertices->push_back(osg::Vec2f(coords.x(), coords.y())); - } -} - - // Rotate by a heading value static inline osg::Matrixf wxRotate(float angle) @@ -271,24 +260,33 @@ NavDisplay::update (double delta_time_sec) } _time += delta_time_sec; - if (_time < _interval){ + if (_time < _updateInterval){ return; } - _time -= _interval; + _time -= _updateInterval; string mode = _Instrument->getStringValue("display-mode", "arc"); _rangeNm = _Instrument->getFloatValue("range", 40.0); - _view_heading = fgGetDouble("/orientation/heading-deg") * SG_DEGREES_TO_RADIANS; - _scale = 200.0; - - bool centre = _radar_centre_node->getBoolValue(); - if (centre) { - _centerTrans = osg::Matrixf::identity(); - } else { - _centerTrans = osg::Matrixf::identity(); - } - - _drawData = _radar_data_node->getBoolValue(); + if (_Instrument->getBoolValue("aircraft-heading-up", true)) { + _view_heading = fgGetDouble("/orientation/heading-deg"); + } else { + _view_heading = _Instrument->getFloatValue("heading-up-deg", 0.0); + } + _view_heading *= SG_DEGREES_TO_RADIANS; + + _scale = _odg->size() / _rangeNm; + _drawData = _radar_data_node->getBoolValue(); + + double xCenterFrac = _Instrument->getDoubleValue("x-center", 0.5); + double yCenterFrac = _Instrument->getDoubleValue("y-center", 0.5); + _centerTrans = osg::Matrixf::translate(xCenterFrac * _odg->size(), + yCenterFrac * _odg->size(), 0.0); + +// scale from nm to display units, rotate so aircraft heading is up +// (as opposed to north), and compensate for centering + _projectMat = osg::Matrixf::scale(_scale, _scale, 1.0) * + wxRotate(-_view_heading) * _centerTrans; + _pos = SGGeod::fromDegFt(_user_lon_node->getDoubleValue(), _user_lat_node->getDoubleValue(), _user_alt_node->getDoubleValue()); @@ -300,8 +298,24 @@ NavDisplay::update (double delta_time_sec) _textGeode->removeDrawables(0, _textGeode->getNumDrawables()); update_aircraft(); + update_stations(); + update_airports(); + update_waypoints(); update_route(); + + osg::Vec2 origin = projectGeod(_pos); + if (_draw_heading_node->getBoolValue()) { + addLine(origin, projectBearingRange(fgGetDouble("/orientation/heading-deg"), _rangeNm), osg::Vec3(1, 1, 1)); + } + if (_draw_track_node->getBoolValue()) { + double groundTrackDeg = fgGetDouble("/instrumentation/gps/indicated-track-true-deg"); + addLine(origin, projectBearingRange(groundTrackDeg, _rangeNm), osg::Vec3(1, 1, 1)); + } + + if (_draw_north_node->getBoolValue()) { + addLine(origin, projectBearingRange(0, _rangeNm), osg::Vec3(0, 1, 1)); + } _symbolPrimSet->set(osg::PrimitiveSet::QUADS, 0, _vertices->size()); _symbolPrimSet->dirty(); @@ -309,6 +323,22 @@ NavDisplay::update (double delta_time_sec) _linePrimSet->dirty(); } +void NavDisplay::addLine(osg::Vec2 a, osg::Vec2 b, const osg::Vec3& color) +{ + _lineVertices->push_back(a); + _lineVertices->push_back(b); + _lineColors->push_back(color); + _lineColors->push_back(color); +} + +osg::Vec2 NavDisplay::projectBearingRange(double bearingDeg, double rangeNm) const +{ + osg::Vec3 p(0, rangeNm, 0.0); + p = wxRotate(bearingDeg * SG_DEGREES_TO_RADIANS).preMult(p); + p = _projectMat.preMult(p); + return osg::Vec2(p.x(), p.y()); +} + osg::Matrixf NavDisplay::project(const SGGeod& geod) const { double rangeM, bearing, az2; @@ -323,35 +353,42 @@ osg::Matrixf NavDisplay::project(const SGGeod& geod) const } +osg::Vec2 NavDisplay::projectGeod(const SGGeod& geod) const +{ + double rangeM, bearing, az2; + SGGeodesy::inverse(_pos, geod, bearing, az2, rangeM); + return projectBearingRange(bearing, rangeM * SG_METER_TO_NM); +} + void -NavDisplay::addSymbol(const SGGeod& pos, int symbolIndex, const std::string& data) +NavDisplay::addSymbol(const SGGeod& pos, int symbolIndex, const std::string& data, const osg::Vec3& color) { - int symbolRow = symbolIndex >> 4; + osg::Vec2 xy = projectGeod(pos); + double scale = 20.0; + int symbolRow = (SYMBOL_TEX_DIM - 1) - (symbolIndex >> 4); int symbolColumn = symbolIndex & 0x0f; - const osg::Vec2f texBase(UNIT * symbolColumn, UNIT * symbolRow); - float size = 600 * UNIT; - osg::Matrixf m(osg::Matrixf::scale(size, size, 1.0f) - * project(pos)); - addQuad(_vertices, _texCoords, m, texBase); - - if (!_drawData) { - return; + for (int i = 0; i < 4; i++) { + _texCoords->push_back(texBase + symbolTexCoords[i]); + osg::Vec2 coord(symbolCoords[i].x() * scale, symbolCoords[i].y() * scale); + _vertices->push_back(xy + coord); + _quadColors->push_back(color); } - + // add data drawable osgText::Text* text = new osgText::Text; text->setFont(_font.get()); text->setFontResolution(12, 12); text->setCharacterSize(_font_size); - - osg::Vec3 dataPos = m.preMult(osg::Vec3(16, 16, 0)); text->setLineSpacing(_font_spacing); - + text->setAlignment(osgText::Text::LEFT_CENTER); text->setText(data); - text->setPosition(osg::Vec3((int) dataPos.x(), (int)dataPos.y(), 0)); + + osg::Vec4 textColor(color.x(), color.y(), color.z(), 1); + text->setColor(textColor); + text->setPosition( osg::Vec3(xy.x() + 16, xy.y(), 0)); _textGeode->addDrawable(text); } @@ -364,35 +401,199 @@ NavDisplay::update_route() RoutePath path(_route->waypts()); for (int w=0; w<_route->numWaypts(); ++w) { - bool isPast = w < _route->currentIndex(); + osg::Vec3 color(1.0, 0.0, 1.0); SGGeodVec gv(path.pathForIndex(w)); if (!gv.empty()) { - osg::Vec3 color(1.0, 0.0, 1.0); - if (isPast) { - color = osg::Vec3(0.5, 0.5, 0.5); - } - - osg::Vec3 pr = project(gv[0]).preMult(osg::Vec3(0.0, 0.0, 0.0)); + osg::Vec2 pr = projectGeod(gv[0]); for (unsigned int i=1; ipush_back(osg::Vec2(pr.x(), pr.y())); - pr = project(gv[i]).preMult(osg::Vec3(0.0, 0.0, 0.0)); - _lineVertices->push_back(osg::Vec2(pr.x(), pr.y())); - - _lineColors->push_back(color); - _lineColors->push_back(color); + osg::Vec2 p = projectGeod(gv[i]); + addLine(pr, p, color); + pr = p; } } // of line drawing flightgear::WayptRef wpt(_route->wayptAtIndex(w)); SGGeod g = path.positionForIndex(w); - int symbolIndex = isPast ? 1 : 0; if (!(g == SGGeod())) { - std::string data = wpt->ident(); - addSymbol(g, symbolIndex, data); + int symbolIndex = (6 << 4); + osg::Vec3 color(1.0, 1.0, 1.0); + // active waypoint is magenta, not white + if (w == _route->currentIndex()) { + color = osg::Vec3(1.0, 0.0, 1.0); + } + + addSymbol(g, symbolIndex, wpt->ident(), color); } } // of waypoints iteration } +void +NavDisplay::update_stations() +{ + FGNavRecord* nav1 = drawTunedNavaid(_navRadio1Node); + FGNavRecord* nav2 = drawTunedNavaid(_navRadio2Node); + + if (_radar_station_node->getBoolValue()) { + osg::Vec3 cyanColor(0, 1, 1); + FGPositioned::TypeFilter filt(FGPositioned::VOR); + FGPositioned::List stations = + FGPositioned::findWithinRange(_pos, _rangeNm, &filt); + + FGPositioned::List::const_iterator it; + for (it = stations.begin(); it != stations.end(); ++it) { + FGPositioned* sta = *it; + if ((sta == nav1) || (sta == nav2)) { + continue; + } + + int symbolIndex = (6 << 4) + 2; + addSymbol(sta->geod(), symbolIndex, sta->ident(), cyanColor); + } + } // of stations beiong drawn +} + +class FixFilter : public FGPositioned::Filter +{ +public: + virtual bool pass(FGPositioned* aPos) const + { + // ignore fixes which end in digits + if (isdigit(aPos->ident()[3]) && isdigit(aPos->ident()[4])) { + return false; + } + + return true; + } + + virtual FGPositioned::Type minType() const { + return FGPositioned::FIX; + } + + virtual FGPositioned::Type maxType() const { + return FGPositioned::FIX; + } + +private: + bool _fixes, _navaids; +}; + +void +NavDisplay::update_waypoints() +{ + if (!_draw_fix_node->getBoolValue()) { + return; + } + + std::set routeWaypts; + for (int w=0; w<_route->numWaypts(); ++w) { + flightgear::WayptRef wpt(_route->wayptAtIndex(w)); + routeWaypts.insert(wpt->source()); + } + + osg::Vec3 cyanColor(0, 1, 1); + FixFilter filt; + FGPositioned::List fixes = + FGPositioned::findWithinRange(_pos, _rangeNm, &filt); + + FGPositioned::List::const_iterator it; + for (it = fixes.begin(); it != fixes.end(); ++it) { + FGPositioned* fix = *it; + if (routeWaypts.count(fix)) { + continue; // part of active route, don't draw here + } + + int symbolIndex = (6 << 4) + 0; + addSymbol(fix->geod(), symbolIndex, fix->ident(), cyanColor); + } // of draw fixes iteration +} + +FGNavRecord* +NavDisplay::drawTunedNavaid(const SGPropertyNode_ptr& radio ) +{ + double mhz = radio->getDoubleValue("frequencies/selected-mhz", 0.0); + FGNavRecord* nav = globals->get_navlist()->findByFreq(mhz, _pos); + if (!nav || (nav->ident() != radio->getStringValue("nav-id"))) { + // station was not found + return NULL; + } + + osg::Vec3 greenColor(0, 1, 0); + int symbolIndex = (6 << 4) + 2; + addSymbol(nav->geod(), symbolIndex, nav->ident(), greenColor); + +// Boeing: only show radial + reciprocal if manually tuned ... hmmmm + osg::Vec2 stationXY = projectGeod(nav->geod()); + SGGeod radialEnd; + double az2; + double trueRadial = radio->getDoubleValue("radials/target-radial-deg"); + SGGeodesy::direct(nav->geod(), trueRadial, + nav->get_range() * SG_NM_TO_METER, radialEnd, az2); + osg::Vec2 radialXY = projectGeod(radialEnd); + + osg::Vec2 d = radialXY - stationXY; + addLine(stationXY - d, radialXY, greenColor); + +// Boeing: if POS is selected, show radial to station + osg::Vec2 posXY = projectGeod(_pos); + addLine(posXY, stationXY, greenColor); + + osgText::Text* text = new osgText::Text; + text->setFont(_font.get()); + text->setFontResolution(12, 12); + text->setCharacterSize(_font_size); + text->setLineSpacing(_font_spacing); + text->setAlignment(osgText::Text::CENTER_BOTTOM); + text->setColor(osg::Vec4(0, 1, 0, 1)); + + stringstream s; + s << "R-" << setw(3) << setfill('0') << static_cast(trueRadial); + text->setText(s.str()); + osg::Vec2 mid = (posXY + stationXY) * 0.5; // radial mid-point + text->setPosition( osg::Vec3(mid.x(), mid.y(), 0)); + _textGeode->addDrawable(text); + + return nav; +} + +void +NavDisplay::update_airports() +{ + FGAirport* dep = _route->departureAirport(), + *arr = _route->destinationAirport(); + + if (_radar_arpt_node->getBoolValue()) { + osg::Vec3 cyanColor(0, 1, 1); + int symbolIndex = (6 << 4) + 3; + double minRunway = _Instrument->getDoubleValue("display-controls/min-runway-len-ft", 0.0); + FGAirport::HardSurfaceFilter filt(minRunway); + FGPositioned::List apts = + FGPositioned::findWithinRange(_pos, _rangeNm, &filt); + + FGPositioned::List::const_iterator it; + for (it = apts.begin(); it != apts.end(); ++it) { + FGPositioned* apt = *it; + if ((apt == dep) || (apt == arr)) { + // added seperately + continue; + } + + addSymbol(apt->geod(), symbolIndex, apt->ident(), cyanColor); + } // of airports iteration + } + + int symbolIndex = (7 << 4) + 1; + osg::Vec3 whiteColor(1, 1, 1); + FGRunway* rwy = _route->departureRunway(); + if (rwy) { + addSymbol(dep->geod(), symbolIndex, dep->ident() + "\n" + rwy->ident(), whiteColor); + } + + rwy = _route->destinationRunway(); + if (rwy) { + addSymbol(arr->geod(), symbolIndex, arr->ident() + "\n" + rwy->ident(), whiteColor); + } +} + void NavDisplay::update_aircraft() { @@ -401,12 +602,11 @@ NavDisplay::update_aircraft() } bool draw_tcas = _radar_tcas_node->getBoolValue(); - bool draw_absolute = _radar_absalt_node->getBoolValue(); - bool draw_echoes = _radar_position_node->getBoolValue(); - bool draw_symbols = _radar_symbol_node->getBoolValue(); - bool draw_data = _radar_data_node->getBoolValue(); - if (!draw_echoes && !draw_symbols && !draw_data) + if (!draw_tcas) { return; + } + + bool draw_absolute = _radar_absalt_node->getBoolValue(); const SGPropertyNode *ai = fgGetNode("/ai/models", true); for (int i = ai->nChildren() - 1; i >= 0; i--) { @@ -422,14 +622,6 @@ NavDisplay::update_aircraft() echo_radius = 1, sigma = 1; else if (name == "multiplayer" || name == "wingman" || name == "static") echo_radius = 1.5, sigma = 1; - else if (name == "ship" || name == "carrier" || name == "escort" ||name == "storm") - echo_radius = 1.5, sigma = 100; - else if (name == "thermal") - echo_radius = 2, sigma = 100; - else if (name == "rocket") - echo_radius = 0.1, sigma = 0.1; - else if (name == "ballistic") - echo_radius = 0.001, sigma = 0.001; else continue; @@ -441,91 +633,45 @@ NavDisplay::update_aircraft() double rangeM, bearing, az2; SGGeodesy::inverse(_pos, aiModelPos, bearing, az2, rangeM); - // if (!inRadarRange(sigma, rangeM)) - // continue; - bearing *= SG_DEGREES_TO_RADIANS; heading *= SG_DEGREES_TO_RADIANS; float radius = rangeM * _scale; - // float angle = relativeBearing(bearing, _view_heading); - bool is_tcas_contact = false; - if (draw_tcas) - { - is_tcas_contact = update_tcas(model,rangeM, + bool is_tcas_contact = update_tcas(model,aiModelPos, _pos.getElevationFt(), aiModelPos.getElevationFt(), - bearing,radius,draw_absolute); - } + draw_absolute); - // data mode - if (draw_symbols && (!draw_tcas)) { - const osg::Vec2f texBase(0, 3 * UNIT); - float size = 600 * UNIT; - osg::Matrixf m(osg::Matrixf::scale(size, size, 1.0f) - * wxRotate(heading - bearing) - * osg::Matrixf::translate(0.0f, radius, 0.0f) - * wxRotate(bearing) * _centerTrans); - addQuad(_vertices, _texCoords, m, texBase); - } - - if (draw_data || is_tcas_contact) { - update_data(model, aiModelPos.getElevationFt(), heading, radius, bearing, false); - } + update_data(model, aiModelPos.getElevationFt(), heading, radius, bearing, false); } // of ai models iteration } /** Update TCAS display. * Return true when processed as TCAS contact, false otherwise. */ bool -NavDisplay::update_tcas(const SGPropertyNode *model,double range,double user_alt,double alt, - double bearing,double radius,bool absMode) +NavDisplay::update_tcas(const SGPropertyNode *model, const SGGeod& modelPos, + double user_alt,double alt, bool absMode) { - int threatLevel=0; - { - // update TCAS symbol - osg::Vec2f texBase; - threatLevel = model->getIntValue("tcas/threat-level",-1); - if (threatLevel == -1) - { - // no TCAS information (i.e. no transponder) => not visible to TCAS - return false; - } - int row = 7 - threatLevel; - int col = 4; - double vspeed = model->getDoubleValue("velocities/vertical-speed-fps"); - if (vspeed < -3.0) // descending - col+=1; - else - if (vspeed > 3.0) // climbing - col+=2; - texBase = osg::Vec2f(col*UNIT,row * UNIT); - float size = 200 * UNIT; - osg::Matrixf m(osg::Matrixf::scale(size, size, 1.0f) - * wxRotate(-bearing) - * osg::Matrixf::translate(0.0f, radius, 0.0f) - * wxRotate(bearing) * _centerTrans); - addQuad(_vertices, _texCoords, m, texBase); + int threatLevel = model->getIntValue("tcas/threat-level",-1); + if (threatLevel == -1) { + // no TCAS information (i.e. no transponder) => not visible to TCAS + return false; } - - { - // update TCAS data - osgText::Text *altStr = new osgText::Text; - altStr->setFont(_font.get()); - altStr->setFontResolution(12, 12); - altStr->setCharacterSize(_font_size); - altStr->setColor(_tcas_colors[threatLevel]); - osg::Matrixf m(wxRotate(-bearing) - * osg::Matrixf::translate(0.0f, radius, 0.0f) - * wxRotate(bearing) * _centerTrans); - - osg::Vec3 pos = m.preMult(osg::Vec3(16, 16, 0)); - // cast to int's, otherwise text comes out ugly - altStr->setLineSpacing(_font_spacing); + + int row = 4; + int col = threatLevel; + double vspeed = model->getDoubleValue("velocities/vertical-speed-fps"); + if (vspeed < -3.0) // descending + row+=1; + // else +// if (vspeed > 3.0) // climbing + // col+=2; + + osg::Vec4 color = _tcas_colors[threatLevel]; stringstream text; - altStr->setAlignment(osgText::Text::LEFT_CENTER); + // altStr->setAlignment(osgText::Text::LEFT_CENTER); int altDif = (alt-user_alt+50)/100; char sign = 0; int dy=0; @@ -541,7 +687,7 @@ NavDisplay::update_tcas(const SGPropertyNode *model,double range,double user_alt altDif = -altDif; dy=-30; } - altStr->setPosition(osg::Vec3((int)pos.x()-30, (int)pos.y()+dy, 0)); + // altStr->setPosition(osg::Vec3((int)pos.x()-30, (int)pos.y()+dy, 0)); if (absMode) { // absolute altitude display @@ -555,11 +701,10 @@ NavDisplay::update_tcas(const SGPropertyNode *model,double range,double user_alt << setprecision(0) << fixed << setw(2) << setfill('0') << altDif << endl; } - - altStr->setText(text.str()); - _textGeode->addDrawable(altStr); - } + addSymbol(modelPos, (col << 4) | row, text.str(), + osg::Vec3(color.r(), color.g(), color.b())); + return true; } diff --git a/src/Instrumentation/NavDisplay.hxx b/src/Instrumentation/NavDisplay.hxx index bedaf6fb0..8d72bb80a 100644 --- a/src/Instrumentation/NavDisplay.hxx +++ b/src/Instrumentation/NavDisplay.hxx @@ -37,6 +37,7 @@ class FGODGauge; class FGRouteMgr; +class FGNavRecord; class NavDisplay : public SGSubsystem { @@ -52,10 +53,7 @@ protected: string _name; int _num; double _time; - double _interval; - double _elapsed_time; - double _persistance; - bool _sim_init_done; + double _updateInterval; SGPropertyNode_ptr _serviceable_node; SGPropertyNode_ptr _Instrument; @@ -80,13 +78,7 @@ private: DisplayMode _display_mode; float _scale; // factor to convert nm to display units - float _angle_offset; float _view_heading; - float _x_offset, _y_offset; - - double _radar_ref_rng; - double _lat, _lon; - bool _drawData; SGPropertyNode_ptr _Radar_controls; @@ -95,7 +87,9 @@ private: SGPropertyNode_ptr _radar_position_node; SGPropertyNode_ptr _radar_data_node; SGPropertyNode_ptr _radar_symbol_node; - + SGPropertyNode_ptr _radar_arpt_node; + SGPropertyNode_ptr _radar_station_node; + SGPropertyNode_ptr _radar_centre_node; SGPropertyNode_ptr _radar_coverage_node; SGPropertyNode_ptr _radar_ref_rng_node; @@ -104,9 +98,16 @@ private: SGPropertyNode_ptr _radar_tcas_node; SGPropertyNode_ptr _radar_absalt_node; + SGPropertyNode_ptr _draw_track_node; + SGPropertyNode_ptr _draw_heading_node; + SGPropertyNode_ptr _draw_north_node; + SGPropertyNode_ptr _draw_fix_node; + SGPropertyNode_ptr _font_node; SGPropertyNode_ptr _ai_enabled_node; - + SGPropertyNode_ptr _navRadio1Node; + SGPropertyNode_ptr _navRadio2Node; + osg::ref_ptr _resultTexture; osg::ref_ptr _symbols; osg::ref_ptr _radarGeode; @@ -117,7 +118,8 @@ private: osg::DrawArrays* _symbolPrimSet; osg::Vec2Array *_vertices; osg::Vec2Array *_texCoords; - + osg::Vec3Array* _quadColors; + osg::Geometry* _lineGeometry; osg::DrawArrays* _linePrimSet; osg::Vec2Array* _lineVertices; @@ -125,6 +127,8 @@ private: osg::Matrixf _centerTrans; + osg::Matrixf _projectMat; + osg::ref_ptr _font; osg::Vec4 _font_color; osg::Vec4 _tcas_colors[4]; @@ -137,14 +141,26 @@ private: void update_route(); void update_aircraft(); - bool update_tcas(const SGPropertyNode *model,double range,double user_alt,double alt, - double bearing,double radius, bool absMode); + void update_stations(); + void update_airports(); + void update_waypoints(); + + bool update_tcas(const SGPropertyNode *model, const SGGeod& modelPos, + double user_alt,double alt, bool absMode); void update_data(const SGPropertyNode *ac, double altitude, double heading, double radius, double bearing, bool selected); void updateFont(); osg::Matrixf project(const SGGeod& geod) const; - void addSymbol(const SGGeod& pos, int symbolIndex, const std::string& data); + osg::Vec2 projectBearingRange(double bearingDeg, double rangeNm) const; + osg::Vec2 projectGeod(const SGGeod& geod) const; + + void addSymbol(const SGGeod& pos, int symbolIndex, + const std::string& data, const osg::Vec3& color); + + void addLine(osg::Vec2 a, osg::Vec2 b, const osg::Vec3& color); + + FGNavRecord* drawTunedNavaid(const SGPropertyNode_ptr& radio ); }; #endif // _INST_ND_HXX diff --git a/src/Instrumentation/od_gauge.hxx b/src/Instrumentation/od_gauge.hxx index 3b3217d5b..932b4847d 100644 --- a/src/Instrumentation/od_gauge.hxx +++ b/src/Instrumentation/od_gauge.hxx @@ -43,7 +43,9 @@ public: virtual void update (double dt); void setSize(int viewSize); - + int size() const + { return textureWH; } + /** * Say if we can render to a texture. * @return true if rtt is available