]> git.mxchange.org Git - flightgear.git/commitdiff
Harald JOHNSEN:
authorehofman <ehofman>
Sat, 8 Oct 2005 11:55:18 +0000 (11:55 +0000)
committerehofman <ehofman>
Sat, 8 Oct 2005 11:55:18 +0000 (11:55 +0000)
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
src/Instrumentation/instrument_mgr.cxx
src/Instrumentation/od_gauge.cxx [new file with mode: 0644]
src/Instrumentation/od_gauge.hxx [new file with mode: 0644]
src/Instrumentation/wxradar.cxx [new file with mode: 0644]
src/Instrumentation/wxradar.hxx [new file with mode: 0644]
src/Main/options.cxx
src/Model/acmodel.cxx

index 77758cb0dcdbad3d6d889030bcc65b030db6a85c..94029b394878a29ec235dba129d01f02d413c60e 100644 (file)
@@ -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
index 30d0221cdd9a1715a68d5bc8ab5c263cefca45d5..37f4da0e3fac346585ac84814f965f0e9e5b7f5b 100644 (file)
 #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 (file)
index 0000000..dabf87c
--- /dev/null
@@ -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 <plib/ssg.h>
+#include <simgear/screen/extensions.hxx>
+#include <simgear/screen/RenderTexture.h>
+#include <simgear/debug/logstream.hxx>
+#include SG_GLU_H
+
+#include <Main/globals.hxx>
+#include <Scenery/scenery.hxx>
+#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 (file)
index 0000000..926fbe8
--- /dev/null
@@ -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 <plib/ssg.h>
+#include <simgear/structure/subsystem_mgr.hxx>
+
+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 (file)
index 0000000..a233433
--- /dev/null
@@ -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 <plib/sg.h>
+#include <plib/ssg.h>
+#include <Main/fg_props.hxx>
+#include <Main/globals.hxx>
+#include <Cockpit/panel.hxx>
+#include <Cockpit/hud.hxx>
+
+#include <simgear/constants.h>
+#include <simgear/misc/sg_path.hxx>
+#include <simgear/environment/visual_enviro.hxx>
+#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 (file)
index 0000000..1d905b5
--- /dev/null
@@ -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 <simgear/props/props.hxx>
+#include <simgear/structure/subsystem_mgr.hxx>
+
+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
index 11b5e7c0bd8f1cbe77eecc1c8b7f1b19fc31df0a..a6f6ea1625d1bee9b63dba4aec4e716ff1c7b382 100644 (file)
@@ -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<string,size_t> 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}
 };
 
index 1edb6911d940d86d60decc2808a51e5c3e21bef9..155c17d9971c5d87846710cb6aed0e21356e8d57 100644 (file)
 #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;
+
 \f
 ////////////////////////////////////////////////////////////////////////
 // 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