From 68f248879cb15562c7b026445f83caf8f2842ae9 Mon Sep 17 00:00:00 2001 From: ehofman Date: Sat, 8 Oct 2005 11:55:18 +0000 Subject: [PATCH] Harald JOHNSEN: Changes ======= - acmodel.cxx : we now have an optional new property (/sim/model/texture-path) that is used as the first path in wich aircraft textures are searched. If textures are not found there then the usual texture path or model path is used ; This allows to replace only needed textures for liveries ; - options.cxx : added a new --livery=xxx option for the user pleasure ; this will just set the /sim/model/texture-path property with /livery/xxxx - od_gauge.cxx, og_gauge.hxx, cockpit.cxx, cockpit.hxx, generic-instrumentation.xml : added an helper class that contain a rendering context for glass instrument or any other opengl drawn instrument ; - wxradar.cxx, instrument_mgr.cxx, wxradar.hxx : first experimentation of a weather radar ; --- src/Instrumentation/Makefile.am | 1 + src/Instrumentation/instrument_mgr.cxx | 6 + src/Instrumentation/od_gauge.cxx | 214 ++++++++++++++++ src/Instrumentation/od_gauge.hxx | 90 +++++++ src/Instrumentation/wxradar.cxx | 322 +++++++++++++++++++++++++ src/Instrumentation/wxradar.hxx | 58 +++++ src/Main/options.cxx | 10 + src/Model/acmodel.cxx | 45 ++++ 8 files changed, 746 insertions(+) create mode 100644 src/Instrumentation/od_gauge.cxx create mode 100644 src/Instrumentation/od_gauge.hxx create mode 100644 src/Instrumentation/wxradar.cxx create mode 100644 src/Instrumentation/wxradar.hxx diff --git a/src/Instrumentation/Makefile.am b/src/Instrumentation/Makefile.am index 77758cb0d..94029b394 100644 --- a/src/Instrumentation/Makefile.am +++ b/src/Instrumentation/Makefile.am @@ -23,6 +23,7 @@ libInstrumentation_a_SOURCES = \ turn_indicator.cxx turn_indicator.hxx \ vertical_speed_indicator.cxx vertical_speed_indicator.hxx \ inst_vertical_speed_indicator.cxx inst_vertical_speed_indicator.hxx \ + od_gauge.hxx od_gauge.cxx wxradar.hxx wxradar.cxx \ tacan.cxx tacan.hxx INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src diff --git a/src/Instrumentation/instrument_mgr.cxx b/src/Instrumentation/instrument_mgr.cxx index 30d0221cd..37f4da0e3 100644 --- a/src/Instrumentation/instrument_mgr.cxx +++ b/src/Instrumentation/instrument_mgr.cxx @@ -36,12 +36,15 @@ #include "turn_indicator.hxx" #include "vertical_speed_indicator.hxx" #include "inst_vertical_speed_indicator.hxx" // (TJ) +#include "od_gauge.hxx" +#include "wxradar.hxx" #include "tacan.hxx" FGInstrumentMgr::FGInstrumentMgr () { set_subsystem("annunciator", new Annunciator); + set_subsystem("od_gauge", new FGODGauge, 1.0); config_props = new SGPropertyNode; @@ -150,6 +153,9 @@ bool FGInstrumentMgr::build () } else if ( name == "vertical-speed-indicator" ) { set_subsystem( "instrument" + temp.str(), new VerticalSpeedIndicator( node ) ); + } else if ( name == "wxradar" ) { + set_subsystem( "instrument" + temp.str(), + new wxRadarBg ( node ), 0.5 ); } else if ( name == "inst-vertical-speed-indicator" ) { // (TJ) set_subsystem( "instrument" + temp.str(), new InstVerticalSpeedIndicator( node ) ); diff --git a/src/Instrumentation/od_gauge.cxx b/src/Instrumentation/od_gauge.cxx new file mode 100644 index 000000000..dabf87c37 --- /dev/null +++ b/src/Instrumentation/od_gauge.cxx @@ -0,0 +1,214 @@ +// Owner Drawn Gauge helper class +// +// Written by Harald JOHNSEN, started May 2005. +// +// Copyright (C) 2005 Harald JOHNSEN - hjohnsen@evc.net +// +// 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, 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA +// +// + +#include +#include +#include +#include +#include SG_GLU_H + +#include
+#include +#include "od_gauge.hxx" + +FGODGauge::FGODGauge() : + rtAvailable( false ), + rt( 0 ) +{ +} + +// done here and not in init() so we don't allocate a rendering context if it is +// never used +void FGODGauge::allocRT () { + GLint colorBits = 0; + glGetIntegerv( GL_BLUE_BITS, &colorBits ); + textureWH = 256; + rt = new RenderTexture(); + if( colorBits < 8 ) + rt->Reset("rgba=5,5,5,1 ctt"); + else + rt->Reset("rgba ctt"); + + if( rt->Initialize(256, 256, true) ) { + SG_LOG(SG_ALL, SG_INFO, "FGODGauge:Initialize sucessfull"); + if (rt->BeginCapture()) + { + SG_LOG(SG_ALL, SG_INFO, "FGODGauge:BeginCapture sucessfull, RTT available"); + rtAvailable = true; + glViewport(0, 0, textureWH, textureWH); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluOrtho2D( -256.0, 256.0, -256.0, 256.0 ); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glDisable(GL_LIGHTING); + glEnable(GL_COLOR_MATERIAL); + glDisable(GL_CULL_FACE); + glDisable(GL_FOG); + glDisable(GL_DEPTH_TEST); + glClearColor(0.0, 0.0, 0.0, 0.0); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + glBindTexture(GL_TEXTURE_2D, 0); + glEnable(GL_TEXTURE_2D); + glEnable(GL_ALPHA_TEST); + glAlphaFunc(GL_GREATER, 0.0f); + glDisable(GL_SMOOTH); + glEnable(GL_BLEND); + glBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_ALPHA ); + rt->EndCapture(); + } else + SG_LOG(SG_ALL, SG_WARN, "FGODGauge:BeginCapture failed, RTT not available, using backbuffer"); + } else + SG_LOG(SG_ALL, SG_WARN, "FGODGauge:Initialize failed, RTT not available, using backbuffer"); +} + +FGODGauge::~FGODGauge() { + delete rt; +} + +void FGODGauge::init () { +} + +void FGODGauge::update (double dt) { +} + +void FGODGauge::beginCapture(int viewSize) { + if( ! rt ) + allocRT(); + if(rtAvailable) { + rt->BeginCapture(); + } + else + set2D(); + textureWH = viewSize; + glViewport(0, 0, textureWH, textureWH); +} + +void FGODGauge::beginCapture(void) { + if( ! rt ) + allocRT(); + if(rtAvailable) { + rt->BeginCapture(); + } + else + set2D(); +} + +void FGODGauge::Clear(void) { + if(rtAvailable) { + glClear(GL_COLOR_BUFFER_BIT); + } + else { + glDisable(GL_BLEND); + glDisable(GL_ALPHA_TEST); + glColor4f(0.0f, 0.0f, 0.0f, 0.0f); + glRectf(-256.0, -256.0, 256.0, 256.0); + glEnable(GL_BLEND); + glBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_ALPHA ); + glEnable(GL_ALPHA_TEST); + } +} + +void FGODGauge::endCapture(GLuint texID) { + glBindTexture(GL_TEXTURE_2D, texID); + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, textureWH, textureWH); + if(rtAvailable) + rt->EndCapture(); + else + set3D(); +} + +void FGODGauge::setSize(int viewSize) { + textureWH = viewSize; + glViewport(0, 0, textureWH, textureWH); +} + +bool FGODGauge::serviceable(void) { + return rtAvailable; +} + +/** + * Locate a texture SSG node in a branch. + */ +static ssgTexture * +find_texture_node (ssgEntity * node, const char * name) +{ + if( node->isA( ssgTypeTexture() ) ) { + ssgTexture *tex = (ssgTexture *) node; + char * texture_name = tex->getFilename(); + if (texture_name != 0 && !strcmp(name, texture_name)) + return tex; + } + else if (node->isAKindOf(ssgTypeBranch())) { + int nKids = node->getNumKids(); + for (int i = 0; i < nKids; i++) { + ssgTexture * result = + find_texture_node(((ssgBranch*)node)->getKid(i), name); + if (result != 0) + return result; + } + } + return 0; +} + +void FGODGauge::set_texture(const char * name, GLuint new_texture) { + ssgEntity * root = globals->get_scenery()->get_aircraft_branch(); + ssgTexture * node = find_texture_node( root, name ); + if( node ) + node->setHandle( new_texture ); +} + +void FGODGauge::set2D() { + glPushAttrib ( GL_ENABLE_BIT | GL_VIEWPORT_BIT | GL_TRANSFORM_BIT | GL_LIGHTING_BIT ) ; + + glDisable(GL_LIGHTING); + glEnable(GL_COLOR_MATERIAL); + glDisable(GL_CULL_FACE); + glDisable(GL_FOG); + glDisable(GL_DEPTH_TEST); + glClearColor(0.0, 0.0, 0.0, 0.0); + glEnable(GL_TEXTURE_2D); + glDisable(GL_SMOOTH); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + glBindTexture(GL_TEXTURE_2D, 0); + + glViewport ( 0, 0, textureWH, textureWH ) ; + glMatrixMode ( GL_PROJECTION ) ; + glPushMatrix () ; + glLoadIdentity () ; + gluOrtho2D( -256.0, 256.0, -256.0, 256.0 ); + glMatrixMode ( GL_MODELVIEW ) ; + glPushMatrix () ; + glLoadIdentity () ; + + glAlphaFunc(GL_GREATER, 0.0f); + +} + +void FGODGauge::set3D() { + glMatrixMode ( GL_PROJECTION ) ; + glPopMatrix () ; + glMatrixMode ( GL_MODELVIEW ) ; + glPopMatrix () ; + glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ; + glPopAttrib () ; +} diff --git a/src/Instrumentation/od_gauge.hxx b/src/Instrumentation/od_gauge.hxx new file mode 100644 index 000000000..926fbe8a4 --- /dev/null +++ b/src/Instrumentation/od_gauge.hxx @@ -0,0 +1,90 @@ +// Owner Drawn Gauge helper class +// +// Written by Harald JOHNSEN, started May 2005. +// +// Copyright (C) 2005 Harald JOHNSEN - hjohnsen@evc.net +// +// 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, 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA +// +// + +#ifndef _OD_GAUGE_HXX +#define _OD_GAUGE_HXX + + +#include +#include + +class RenderTexture; + +/** + * Owner Drawn Gauge helper class. + */ +class FGODGauge : public SGSubsystem { + +public: + FGODGauge ( SGPropertyNode *node ); + FGODGauge(); + ~FGODGauge(); + virtual void init (); + virtual void update (double dt); + + /** + * Start the rendering of the RTT context. + * @param viewSize size of the destination texture + */ + void beginCapture(int viewSize); + /** + * Start the rendering of the RTT context. + */ + void beginCapture(void); + /** + * Clear the background. + */ + void Clear(void); + /** + * Finish rendering and save the buffer to a texture. + * @param texID name of a gl texture + */ + void endCapture(GLuint texID); + /** + * Set the size of the destination texture. + * @param viewSize size of the destination texture + */ + void setSize(int viewSize); + /** + * Say if we can render to a texture. + * @return true if rtt is available + */ + bool serviceable(void); + /** + * Replace an opengl texture name inside the aircraft scene graph. + * This is to replace a static texture by a dynamic one + * @param name texture filename + * @param new_texture dynamic texture to replace the old one + */ + void set_texture(const char * name, GLuint new_texture); + +private: + int textureWH; + RenderTexture *rt; + bool rtAvailable; + + void allocRT(void); + void set2D(void); + void set3D(void); +}; + +#endif // _OD_GAUGE_HXX diff --git a/src/Instrumentation/wxradar.cxx b/src/Instrumentation/wxradar.cxx new file mode 100644 index 000000000..a233433c1 --- /dev/null +++ b/src/Instrumentation/wxradar.cxx @@ -0,0 +1,322 @@ +// Wx Radar background texture +// +// Written by Harald JOHNSEN, started May 2005. +// +// Copyright (C) 2005 Harald JOHNSEN - hjohnsen@evc.net +// +// 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, 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA +// +// + +#include +#include +#include
+#include
+#include +#include + +#include +#include +#include +#include "instrument_mgr.hxx" +#include "od_gauge.hxx" +#include "wxradar.hxx" + +// texture name to use in 2D and 3D instruments +static const char *odgauge_name = "Aircraft/Instruments/Textures/od_wxradar.rgb"; + +wxRadarBg::wxRadarBg ( SGPropertyNode *node) : + name("wxRadar"), + num(0), + resultTexture( 0 ), + wxEcho( 0 ), + last_switchKnob( "off" ), + sim_init_done ( false ), + odg( 0 ) +{ + int i; + for ( i = 0; i < node->nChildren(); ++i ) { + SGPropertyNode *child = node->getChild(i); + string cname = child->getName(); + string cval = child->getStringValue(); + if ( cname == "name" ) { + name = cval; + } else if ( cname == "number" ) { + num = child->getIntValue(); + } else { + SG_LOG( SG_INSTR, SG_WARN, "Error in wxRadar config logic" ); + if ( name.length() ) { + SG_LOG( SG_INSTR, SG_WARN, "Section = " << name ); + } + } + } +} + +wxRadarBg::wxRadarBg () +{ +} + +wxRadarBg::~wxRadarBg () +{ +} + +void +wxRadarBg::init () +{ + string branch; + branch = "/instrumentation/" + name; + + _Instrument = fgGetNode(branch.c_str(), num, true ); + _serviceable_node = _Instrument->getChild("serviceable", 0, true); + resultTexture = FGTextureManager::createTexture( odgauge_name ); + resultTexture->ref(); + SGPath tpath(globals->get_fg_root()); + tpath.append("Aircraft/Instruments/Textures/wxecho.rgb"); + // no mipmap or else alpha will mix with pixels on the border of shapes, ruining the effect + wxEcho = new ssgTexture( tpath.c_str(), false, false, false); + wxEcho->ref(); + + _Instrument->setFloatValue("trk", 0.0); + _Instrument->setFloatValue("tilt", 0.0); + _Instrument->setStringValue("status",""); + // those properties are used by a radar instrument of a MFD + // input switch = OFF | TST | STBY | ON + // input mode = WX | WXA | MAP + // ouput status = STBY | TEST | WX | WXA | MAP | blank + // input lightning = true | false + // input TRK = +/- n degrees + // input TILT = +/- n degree + // input autotilt = true | false + // input range = n nm (20/40/80) + // input display-mode = arc | rose | map | plan + + FGInstrumentMgr *imgr = (FGInstrumentMgr *) globals->get_subsystem("instrumentation"); + odg = (FGODGauge *) imgr->get_subsystem("od_gauge"); +} + +void +wxRadarBg::update (double delta_time_sec) +{ + if( ! sim_init_done ) { + if( ! fgGetBool("sim/sceneryloaded", false) ) + return; + sim_init_done = true; + } + if ( !odg || ! _serviceable_node->getBoolValue() ) { + _Instrument->setStringValue("status",""); + return; + } + string switchKnob = _Instrument->getStringValue("switch", "on"); + string modeButton = _Instrument->getStringValue("mode", "wx"); + bool drawLightning = _Instrument->getBoolValue("lightning", true); + float range_nm = _Instrument->getFloatValue("range", 40.0); + float range_m = range_nm * SG_NM_TO_METER; + + if( last_switchKnob != switchKnob ) { + // since 3D models don't share textures with the rest of the world + // we must locate them and replace their handle by hand + // only do that when the instrument is turned on + if( last_switchKnob == "off" ) + odg->set_texture( odgauge_name, resultTexture->getHandle()); + last_switchKnob = switchKnob; + } + odg->beginCapture(256); + odg->Clear(); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glPushMatrix(); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + glBindTexture(GL_TEXTURE_2D, 0); + if( switchKnob == "off" ) { + _Instrument->setStringValue("status",""); + } else if( switchKnob == "stby" ) { + _Instrument->setStringValue("status","STBY"); + } else if( switchKnob == "tst" ) { + _Instrument->setStringValue("status","TST"); + // find something interesting to do... + } else { + string display_mode = _Instrument->getStringValue("display-mode", "arc"); + // pretend we have a scan angle bigger then the FOV + // TODO:check real fov, enlarge if < nn, and do clipping if > mm + const float fovFactor = 1.45f; + float view_heading = get_heading() * SG_DEGREES_TO_RADIANS; + float range = 200.0f / range_nm; + _Instrument->setStringValue("status", modeButton.c_str()); + if( display_mode == "arc" ) { + glTranslatef(0.0f, -180.0f, 0.0f); + range = 2*180.0f / range_nm; + } else if( display_mode == "map" ) { +// float view_heading = get_track() * SG_DEGREES_TO_RADIANS; + } else if( display_mode == "plan" ) { + // no sense I presume + float view_heading = 0.0; + } else { + // rose + } + range /= SG_NM_TO_METER; + // we will rotate the echo quads, this gives a better rendering + const float rot_x = cos ( view_heading ); + const float rot_y = sin ( view_heading ); + + list_of_SGWxRadarEcho *radarEcho = sgEnviro.get_radar_echo(); + list_of_SGWxRadarEcho::iterator iradarEcho; + const float LWClevel[] = { 0.1f, 0.5f, 2.1f }; + const float symbolSize = 1.0f / 8.0f ; + // draw the radar echo, we do that in 3 passes, one for each color level + // this is to 'merge' same colors together + glBindTexture(GL_TEXTURE_2D, wxEcho->getHandle() ); + glColor3f(1.0f, 1.0f, 1.0f); + glBegin( GL_QUADS ); + + for(int level = 0; level <= 2 ; level++ ) { + float col = level * symbolSize; + for(iradarEcho = radarEcho->begin() ; iradarEcho != radarEcho->end() ; iradarEcho++ ) { + int cloudId = (iradarEcho->cloudId) ; + bool upgrade = ((cloudId >> 5) & 1); + float lwc = iradarEcho->LWC + (upgrade ? 1.0f : 0.0f); + // skip ns + if( iradarEcho->LWC >= 0.5 && iradarEcho->LWC <= 0.6) + continue; + if( (! iradarEcho->lightning) && ( lwc >= LWClevel[level]) ) { + float dist = sgSqrt( iradarEcho->dist ); + float size = iradarEcho->radius * 2.0; + if( dist - size > range_m ) + continue; + dist = dist * range; + size = size * range; + // compute the relative angle from the view direction + float angle = ( view_heading + iradarEcho->heading ); + if( angle > SG_PI ) + angle -= 2.0*SG_PI; + if( angle < - SG_PI ) + angle += 2.0*SG_PI; + // and apply a fov factor to simulate a greater scan angle + angle = angle * fovFactor + SG_PI / 2.0; + float x = cos( angle ) * dist; + float y = sin( angle ) * dist; + // use different shapes so the display is less boring + float row = symbolSize * (float) (4 + (cloudId & 3) ); + float size_x = rot_x * size; + float size_y = rot_y * size; + glTexCoord2f( col, row); + glVertex2f( x - size_x, y - size_y); + glTexCoord2f( col+symbolSize, row); + glVertex2f( x + size_y, y - size_x); + glTexCoord2f( col+symbolSize, row+symbolSize); + glVertex2f( x + size_x, y + size_y); + glTexCoord2f( col, row+symbolSize); + glVertex2f( x - size_y, y + size_x); + } + } + } + glEnd(); // GL_QUADS + + // draw lightning echos + if( drawLightning ) { + float col = 3 * symbolSize; + float row = 4 * symbolSize; + for(iradarEcho = radarEcho->begin() ; iradarEcho != radarEcho->end() ; iradarEcho++ ) { + if( iradarEcho->lightning ) { + float dist = iradarEcho->dist; + dist = dist * range; + float angle = (view_heading - iradarEcho->heading); + if( angle > SG_PI ) + angle -= 2.0*SG_PI; + if( angle < - SG_PI ) + angle += 2.0*SG_PI; + angle = angle * fovFactor - SG_PI / 2.0; + float x = cos( angle ) * dist; + float y = sin( angle ) * dist; + glColor3f(1.0f, 1.0f, 1.0f); + float size = symbolSize * 0.5f; + glBegin( GL_QUADS ); + glTexCoord2f( col, row); + glVertex2f( x - size, y - size); + glTexCoord2f( col+symbolSize, row); + glVertex2f( x + size, y - size); + glTexCoord2f( col+symbolSize, row+symbolSize); + glVertex2f( x + size, y + size); + glTexCoord2f( col, row+symbolSize); + glVertex2f( x - size, y + size); + glEnd(); + } + } + } + // erase what is out of sight of antenna + /* + |\ /| + | \ / | + | \ / | + --------- + | | + | | + --------- + */ + float yOffset = 180.0f, xOffset = 256.0f; + if( display_mode != "arc" ) { + yOffset = 40.0f; + xOffset = 240.0f; + } + glDisable(GL_BLEND); + glColor4f(1.0f, 0.0f, 0.0f, 0.01f); + glBegin( GL_QUADS ); + glTexCoord2f( 0.5f, 0.25f); + glVertex2f(-xOffset, 0.0 + yOffset); + glTexCoord2f( 1.0f, 0.25f); + glVertex2f(xOffset, 0.0 + yOffset); + glTexCoord2f( 1.0f, 0.5f); + glVertex2f(xOffset, 256.0 + yOffset); + glTexCoord2f( 0.5f, 0.5f); + glVertex2f(-xOffset, 256.0 + yOffset); + glEnd(); + + glColor4f(0.0f, 0.0f, 0.0f, 0.0f); +// glColor4f(0.0f, 1.0f, 0.0f, 1.0f); + glDisable(GL_ALPHA_TEST); + glBindTexture(GL_TEXTURE_2D, 0); + + glBegin( GL_TRIANGLES ); + glVertex2f(0.0, 0.0); + glVertex2f(-256.0, 0.0); + glVertex2f(-256.0, 256.0); + + glVertex2f(0.0, 0.0); + glVertex2f(256.0, 0.0); + glVertex2f(256.0, 256.0); + + glVertex2f(-256, 0.0); + glVertex2f(256.0, 0.0); + glVertex2f(-256.0, -256.0); + + glVertex2f(256, 0.0); + glVertex2f(256.0, -256.0); + glVertex2f(-256.0, -256.0); + glEnd(); + + // DEBUG only +/* glColor4f(1.0f, 0.0f, 0.0f, 1.0f); + glBegin( GL_LINES ); + glVertex2f(0.0, 0.0); + glVertex2f(-256.0, 256.0); + glVertex2f(0.0, 0.0); + glVertex2f(256.0, 256.0); + glEnd();*/ + + glEnable(GL_BLEND); + glEnable(GL_ALPHA_TEST); + } + glPopMatrix(); + odg->endCapture( resultTexture->getHandle() ); +} diff --git a/src/Instrumentation/wxradar.hxx b/src/Instrumentation/wxradar.hxx new file mode 100644 index 000000000..1d905b53d --- /dev/null +++ b/src/Instrumentation/wxradar.hxx @@ -0,0 +1,58 @@ +// Wx Radar background texture +// +// Written by Harald JOHNSEN, started May 2005. +// +// Copyright (C) 2005 Harald JOHNSEN - hjohnsen@evc.net +// +// 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, 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA +// +// + +#ifndef _INST_WXRADAR_HXX +#define _INST_WXRADAR_HXX + +#include +#include + +class ssgTexture; +class FGODGauge; + +class wxRadarBg : public SGSubsystem { + + +public: + + wxRadarBg ( SGPropertyNode *node ); + wxRadarBg (); + virtual ~wxRadarBg (); + + virtual void init (); + virtual void update (double dt); + +private: + + string name; + int num; + + SGPropertyNode_ptr _serviceable_node; + SGPropertyNode_ptr _Instrument; + ssgTexture *resultTexture; + ssgTexture *wxEcho; + string last_switchKnob; + bool sim_init_done; + FGODGauge *odg; +}; + +#endif // _INST_WXRADAR_HXX diff --git a/src/Main/options.cxx b/src/Main/options.cxx index 11b5e7c0b..a6f6ea162 100644 --- a/src/Main/options.cxx +++ b/src/Main/options.cxx @@ -1152,6 +1152,15 @@ fgOptDME( const char *arg ) return FG_OPTIONS_OK; } +static int +fgOptLivery( const char *arg ) +{ + string opt = arg; + string livery_path = "livery/" + opt; + fgSetString("/sim/model/texture-path", livery_path.c_str() ); + return FG_OPTIONS_OK; +} + static map fgOptionMap; /* @@ -1352,6 +1361,7 @@ struct OptionDesc { {"adf", true, OPTION_FUNC, "", false, "", fgOptADF }, {"dme", true, OPTION_FUNC, "", false, "", fgOptDME }, {"min-status", true, OPTION_STRING, "/sim/aircraft-min-status", false, "all", 0 }, + {"livery", true, OPTION_FUNC, "", false, "", fgOptLivery }, {0} }; diff --git a/src/Model/acmodel.cxx b/src/Model/acmodel.cxx index 1edb6911d..155c17d99 100644 --- a/src/Model/acmodel.cxx +++ b/src/Model/acmodel.cxx @@ -31,6 +31,37 @@ #include "acmodel.hxx" +class fgLoaderOptions : ssgLoaderOptions { + +public: + virtual void makeTexturePath ( char* path, const char *fname ) const ; + string livery_path; + +}; + +void fgLoaderOptions::makeTexturePath ( char *path, const char *fname ) const +{ + /* Remove all leading path information. */ + const char* seps = "\\/" ; + const char* fn = & fname [ strlen ( fname ) - 1 ] ; + for ( ; fn != fname && strchr(seps,*fn) == NULL ; fn-- ) + /* Search back for a seperator */ ; + if ( strchr(seps,*fn) != NULL ) + fn++ ; + fname = fn ; + // if we have a livery path and the texture is found there then we use that + // path in priority, if the texture was not found or we add no additional + // livery path then we use the current model path or model/texture-path + if( livery_path.size() ) { + make_path( path, livery_path.c_str(), fname ); + if( ulFileExists( path ) ) + return; + } + make_path ( path, texture_dir, fname ) ; +} + +static fgLoaderOptions _fgLoaderOptions; + //////////////////////////////////////////////////////////////////////// // Implementation of FGAircraftModel @@ -60,8 +91,21 @@ FGAircraftModel::~FGAircraftModel () void FGAircraftModel::init () { + ssgLoaderOptions *currLoaderOptions = ssgGetCurrentOptions(); + ssgSetCurrentOptions( (ssgLoaderOptions*)&_fgLoaderOptions ); _aircraft = new SGModelPlacement; string path = fgGetString("/sim/model/path", "Models/Geometry/glider.ac"); + string texture_path = fgGetString("/sim/model/texture-path"); + if( texture_path.size() ) { + SGPath temp_path; + if ( !ulIsAbsolutePathName( texture_path.c_str() ) ) { + temp_path = globals->get_fg_root(); + temp_path.append( SGPath( path ).dir() ); + temp_path.append( texture_path ); + _fgLoaderOptions.livery_path = temp_path.str(); + } else + _fgLoaderOptions.livery_path = texture_path; + } try { ssgBranch *model = fgLoad3DModelPanel( globals->get_fg_root(), path, @@ -83,6 +127,7 @@ FGAircraftModel::init () // Register that one at the scenery manager globals->get_scenery()->register_placement_transform(_aircraft->getTransform()); + ssgSetCurrentOptions( currLoaderOptions ); } void -- 2.39.5