1
0
Fork 0

Merge branch 'next' into durk-atc

This commit is contained in:
Durk Talsma 2011-08-08 20:20:21 +02:00
commit b5025ccf5d
8 changed files with 330 additions and 298 deletions

View file

@ -65,7 +65,7 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="fltkd.lib ul_d.lib comctl32.lib wsock32.lib zlibd.lib sg_d.lib"
AdditionalDependencies="fltkd.lib comctl32.lib wsock32.lib zlibd.lib"
LinkIncremental="2"
AdditionalLibraryDirectories="..\..\..\..\3rdParty\lib"
GenerateDebugInformation="true"
@ -145,7 +145,7 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="fltkd.lib ul_d.lib comctl32.lib wsock32.lib zlibd.lib sg_d.lib"
AdditionalDependencies="fltkd.lib comctl32.lib wsock32.lib zlibd.lib"
LinkIncremental="2"
AdditionalLibraryDirectories="..\..\..\..\3rdParty.x64\lib"
GenerateDebugInformation="true"
@ -226,7 +226,7 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="fltk.lib ul.lib sg.lib comctl32.lib wsock32.lib zlib.lib"
AdditionalDependencies="fltk.lib comctl32.lib wsock32.lib zlib.lib"
LinkIncremental="1"
AdditionalLibraryDirectories="..\..\..\..\3rdParty\lib"
GenerateDebugInformation="false"
@ -309,7 +309,7 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="fltk.lib ul.lib sg.lib comctl32.lib wsock32.lib zlib.lib"
AdditionalDependencies="fltk.lib comctl32.lib wsock32.lib zlib.lib"
LinkIncremental="1"
AdditionalLibraryDirectories="..\..\..\..\3rdParty.x64\lib"
GenerateDebugInformation="false"

View file

@ -219,6 +219,10 @@ FGEnvironmentMgr::bind ()
&SGSky::get_3dCloudVisRange,
&SGSky::set_3dCloudVisRange);
_tiedProperties.Tie("clouds3d-wrap", thesky,
&SGSky::get_3dCloudWrap,
&SGSky::set_3dCloudWrap);
// _tiedProperties.Tie("lightning-enable", &sgEnviro,
// &SGEnviro::get_lightning_enable_state,
// &SGEnviro::set_lightning_enable_state);

View file

@ -31,14 +31,16 @@
#include <Main/fg_props.hxx>
#include <boost/foreach.hpp>
#include <simgear/structure/exception.hxx>
#include <simgear/misc/strutils.hxx>
#include <simgear/props/tiedpropertylist.hxx>
#include <simgear/io/HTTPClient.hxx>
#include <simgear/io/HTTPRequest.hxx>
#include <simgear/timing/sg_time.hxx>
#include <algorithm>
#if defined(ENABLE_THREADS)
#include <OpenThreads/Thread>
#include <simgear/threads/SGQueue.hxx>
#endif
using simgear::PropertyList;
@ -110,6 +112,7 @@ protected:
simgear::TiedPropertyList _tiedProperties;
typedef std::vector<LiveMetarProperties_ptr> MetarPropertiesList;
MetarPropertiesList _metarProperties;
};
/* -------------------------------------------------------------------------------- */
@ -195,86 +198,95 @@ public:
virtual void update (bool first, double delta_time_sec);
virtual void shutdown ();
class MetarLoadRequest {
public:
MetarLoadRequest( const string & stationId ) :
_stationId(stationId),
_proxyHost(fgGetNode("/sim/presets/proxy/host", true)->getStringValue()),
_proxyPort(fgGetNode("/sim/presets/proxy/port", true)->getStringValue()),
_proxyAuth(fgGetNode("/sim/presets/proxy/authentication", true)->getStringValue())
{}
MetarLoadRequest( const MetarLoadRequest & other ) :
_stationId(other._stationId),
_proxyHost(other._proxyAuth),
_proxyPort(other._proxyPort),
_proxyAuth(other._proxyAuth)
{}
string _stationId;
string _proxyHost;
string _proxyPort;
string _proxyAuth;
private:
};
class MetarLoadResponse {
public:
MetarLoadResponse( const string & stationId, const string metar ) {
_stationId = stationId;
_metar = metar;
}
MetarLoadResponse( const MetarLoadResponse & other ) {
_stationId = other._stationId;
_metar = other._metar;
}
string _stationId;
string _metar;
};
/**
* callback from MetarGetRequest when a download succeeds
*/
void gotMetar(const string& stationId, const string& metar);
private:
double _positionTimeToLive;
double _requestTimer;
#if defined(ENABLE_THREADS)
class MetarLoadThread : public OpenThreads::Thread {
public:
MetarLoadThread( long maxAge );
virtual ~MetarLoadThread( ) { stop(); }
void requestMetar( const MetarLoadRequest & metarRequest, bool background = true );
bool hasMetar() { return _responseQueue.size() > 0; }
MetarLoadResponse getMetar() { return _responseQueue.pop(); }
virtual void run();
void stop();
private:
void fetch( const MetarLoadRequest & );
long _maxAge;
long _minRequestInterval;
volatile bool _stop;
SGBlockingQueue <MetarLoadRequest> _requestQueue;
SGBlockingQueue <MetarLoadResponse> _responseQueue;
};
MetarLoadThread * _metarLoadThread;
#endif
simgear::HTTP::Client _http;
};
class MetarGetRequest : public simgear::HTTP::Request
{
public:
MetarGetRequest(NoaaMetarRealWxController* con, const string& s) :
Request(""),
stationId(s),
fromProxy(false),
wxController(con)
{
setUrl("http://weather.noaa.gov/pub/data/observations/metar/stations/" + stationId + ".TXT");
}
virtual string_list requestHeaders() const
{
string_list r;
r.push_back("X-Time");
return r;
}
virtual string header(const string& name) const
{
if (name == "X-Time") {
char buf[16];
snprintf(buf, 16, "%ld", globals->get_time_params()->get_cur_time());
return buf;
}
return Request::header(name);
}
virtual void responseHeader(const string& key, const string& value)
{
if (key == "x-metarproxy") {
fromProxy = true;
}
}
virtual void gotBodyData(const char* s, int n)
{
metar += string(s, n);
}
virtual void responseComplete()
{
if (responseCode() == 200) {
wxController->gotMetar(stationId, metar);
} else {
SG_LOG(SG_IO, SG_WARN, "metar download failed:" << url() << ": reason:" << responseReason());
}
}
bool fromMetarProxy() const
{ return fromProxy; }
private:
string stationId;
string metar;
bool fromProxy;
NoaaMetarRealWxController* wxController;
};
NoaaMetarRealWxController::NoaaMetarRealWxController( SGPropertyNode_ptr rootNode ) :
BasicRealWxController(rootNode),
_positionTimeToLive(0.0),
_requestTimer(0.0)
{
#if defined(ENABLE_THREADS)
_metarLoadThread = new MetarLoadThread(getMetarMaxAgeMin());
_metarLoadThread->start();
#endif
string proxyHost(fgGetString("/sim/presets/proxy/host"));
int proxyPort(fgGetInt("/sim/presets/proxy/port"));
string proxyAuth(fgGetString("/sim/presets/proxy/auth"));
if (!proxyHost.empty()) {
_http.setProxy(proxyHost, proxyPort, proxyAuth);
}
}
void NoaaMetarRealWxController::shutdown()
{
#if defined(ENABLE_THREADS)
if( _metarLoadThread ) {
delete _metarLoadThread;
_metarLoadThread = NULL;
}
#endif // ENABLE_THREADS
}
NoaaMetarRealWxController::~NoaaMetarRealWxController()
@ -283,6 +295,8 @@ NoaaMetarRealWxController::~NoaaMetarRealWxController()
void NoaaMetarRealWxController::update( bool first, double dt )
{
_http.update();
_positionTimeToLive -= dt;
_requestTimer -= dt;
@ -315,143 +329,32 @@ void NoaaMetarRealWxController::update( bool first, double dt )
if( _requestTimer <= 0.0 ) {
_requestTimer = 10.0;
BOOST_FOREACH(LiveMetarProperties* p, _metarProperties) {
if( p->getTimeToLive() > 0.0 ) continue;
const std::string & stationId = p->getStationId();
if( stationId.empty() ) continue;
for( MetarPropertiesList::iterator it = _metarProperties.begin();
it != _metarProperties.end(); it++ ) {
if( (*it)->getTimeToLive() > 0.0 ) continue;
const std::string & stationId = (*it)->getStationId();
if( stationId.empty() ) continue;
SG_LOG(SG_ALL, SG_INFO,
"NoaaMetarRealWxController::update(): spawning load request for station-id '" << stationId << "'" );
SG_LOG(SG_ALL, SG_INFO,
"NoaaMetarRealWxController::update(): spawning load request for station-id '" << stationId << "'" );
MetarLoadRequest request( stationId );
// load the metar for the nearest airport in the foreground if the fdm is uninitialized
// to make sure a metar is received
// before the automatic runway selection code runs. All subsequent calls
// run in the background
bool background = fgGetBool("/sim/fdm-initialized", false ) || it != _metarProperties.begin();
_metarLoadThread->requestMetar( request, background );
}
}
// pick all the received responses from the result queue and update the associated
// property tree
while( _metarLoadThread->hasMetar() ) {
MetarLoadResponse metar = _metarLoadThread->getMetar();
SG_LOG( SG_ALL, SG_INFO, "NoaaMetarRwalWxController::update() received METAR for " << metar._stationId << ": " << metar._metar );
for( MetarPropertiesList::iterator it = _metarProperties.begin();
it != _metarProperties.end(); it++ ) {
if( (*it)->getStationId() != metar._stationId )
continue;
(*it)->setTimeToLive(900);
(*it)->setMetar( metar._metar );
}
_http.makeRequest(new MetarGetRequest(this, stationId));
} // of MetarProperties iteration
}
}
/* -------------------------------------------------------------------------------- */
#if defined(ENABLE_THREADS)
NoaaMetarRealWxController::MetarLoadThread::MetarLoadThread( long maxAge ) :
_maxAge(maxAge),
_minRequestInterval(2000),
_stop(false)
void NoaaMetarRealWxController::gotMetar(const string& stationId, const string& metar)
{
}
void NoaaMetarRealWxController::MetarLoadThread::requestMetar( const MetarLoadRequest & metarRequest, bool background )
{
if( background ) {
if( _requestQueue.size() > 10 ) {
SG_LOG(SG_ALL,SG_ALERT,
"NoaaMetarRealWxController::MetarLoadThread::requestMetar() more than 10 outstanding METAR requests, dropping "
<< metarRequest._stationId );
return;
}
_requestQueue.push( metarRequest );
} else {
fetch( metarRequest );
SG_LOG( SG_ALL, SG_INFO, "NoaaMetarRwalWxController::update() received METAR for " << stationId << ": " << metar );
BOOST_FOREACH(LiveMetarProperties* p, _metarProperties) {
if (p->getStationId() != stationId)
continue;
p->setTimeToLive(900);
p->setMetar( metar );
}
}
void NoaaMetarRealWxController::MetarLoadThread::stop()
{
// set stop flag and wake up the thread with an empty request
_stop = true;
MetarLoadRequest request("");
requestMetar(request);
join();
}
void NoaaMetarRealWxController::MetarLoadThread::run()
{
SGTimeStamp lastRun = SGTimeStamp::fromSec(0);
for( ;; ) {
SGTimeStamp dt = SGTimeStamp::now() - lastRun;
long delayMs = _minRequestInterval - dt.getSeconds() * 1000;
while (( delayMs > 0 ) && !_stop)
{
// sleep no more than 3 seconds at a time, otherwise shutdown response is too slow
long sleepMs = (delayMs>3000) ? 3000 : delayMs;
microSleep( sleepMs * 1000 );
delayMs -= sleepMs;
}
if (_stop)
break;
lastRun = SGTimeStamp::now();
const MetarLoadRequest request = _requestQueue.pop();
if (( request._stationId.size() == 0 ) || _stop)
break;
fetch( request );
}
}
void NoaaMetarRealWxController::MetarLoadThread::fetch( const MetarLoadRequest & request )
{
SGSharedPtr<FGMetar> result = NULL;
try {
result = new FGMetar( request._stationId, request._proxyHost, request._proxyPort, request._proxyAuth );
_minRequestInterval = 2000;
} catch (const sg_io_exception& e) {
SG_LOG( SG_GENERAL, SG_WARN, "NoaaMetarRealWxController::fetchMetar(): can't get METAR for "
<< request._stationId << ":" << e.getFormattedMessage().c_str() );
_minRequestInterval += _minRequestInterval/2;
if( _minRequestInterval > 30000 )
_minRequestInterval = 30000;
return;
}
string reply = result->getData();
std::replace(reply.begin(), reply.end(), '\n', ' ');
string metar = simgear::strutils::strip( reply );
if( metar.empty() ) {
SG_LOG( SG_GENERAL, SG_WARN, "NoaaMetarRealWxController::fetchMetar(): dropping empty METAR for "
<< request._stationId );
return;
}
if( _maxAge && result->getAge_min() > _maxAge ) {
SG_LOG( SG_GENERAL, SG_ALERT, "NoaaMetarRealWxController::fetchMetar(): dropping outdated METAR "
<< metar );
return;
}
MetarLoadResponse response( request._stationId, metar );
_responseQueue.push( response );
}
#endif
/* -------------------------------------------------------------------------------- */
RealWxController * RealWxController::createInstance( SGPropertyNode_ptr rootNode )

View file

@ -60,6 +60,20 @@ FGEventHandler::FGEventHandler() :
numlockKeyMap[GUIEventAdapter::KEY_KP_Home] = '7';
numlockKeyMap[GUIEventAdapter::KEY_KP_Up] = '8';
numlockKeyMap[GUIEventAdapter::KEY_KP_Page_Up] = '9';
numlockKeyMap[GUIEventAdapter::KEY_KP_Delete] = '.';
// mapping when NumLock is off
noNumlockKeyMap[GUIEventAdapter::KEY_KP_Insert] = PU_KEY_INSERT;
noNumlockKeyMap[GUIEventAdapter::KEY_KP_End] = PU_KEY_END;
noNumlockKeyMap[GUIEventAdapter::KEY_KP_Down] = PU_KEY_DOWN;
noNumlockKeyMap[GUIEventAdapter::KEY_KP_Page_Down] = PU_KEY_PAGE_DOWN;
noNumlockKeyMap[GUIEventAdapter::KEY_KP_Left] = PU_KEY_LEFT;
noNumlockKeyMap[GUIEventAdapter::KEY_KP_Begin] = '5';
noNumlockKeyMap[GUIEventAdapter::KEY_KP_Right] = PU_KEY_RIGHT;
noNumlockKeyMap[GUIEventAdapter::KEY_KP_Home] = PU_KEY_HOME;
noNumlockKeyMap[GUIEventAdapter::KEY_KP_Up] = PU_KEY_UP;
noNumlockKeyMap[GUIEventAdapter::KEY_KP_Page_Up] = PU_KEY_PAGE_UP;
noNumlockKeyMap[GUIEventAdapter::KEY_KP_Delete] = 127;
for (int i = 0; i < 128; i++)
release_keys[i] = i;
@ -259,7 +273,6 @@ void FGEventHandler::handleKey(const osgGA::GUIEventAdapter& ea, int& key,
case GUIEventAdapter::KEY_F10: key = PU_KEY_F10; break;
case GUIEventAdapter::KEY_F11: key = PU_KEY_F11; break;
case GUIEventAdapter::KEY_F12: key = PU_KEY_F12; break;
case GUIEventAdapter::KEY_KP_Delete: key = '.'; break;
case GUIEventAdapter::KEY_KP_Enter: key = '\r'; break;
case GUIEventAdapter::KEY_KP_Add: key = '+'; break;
case GUIEventAdapter::KEY_KP_Divide: key = '/'; break;
@ -268,18 +281,30 @@ void FGEventHandler::handleKey(const osgGA::GUIEventAdapter& ea, int& key,
}
osgGA::GUIEventAdapter::EventType eventType = ea.getEventType();
std::map<int, int>::iterator numPadIter = numlockKeyMap.find(key);
if (numPadIter != numlockKeyMap.end()) {
#ifdef __APPLE__
// Num Lock is always true on Mac
// Num Lock is always true on Mac
std::map<int, int>::iterator numPadIter = numlockKeyMap.find(key);
if (numPadIter != numlockKeyMap.end()) {
key = numPadIter->second;
}
#else
if (ea.getModKeyMask() & osgGA::GUIEventAdapter::MODKEY_NUM_LOCK) {
if (ea.getModKeyMask() & osgGA::GUIEventAdapter::MODKEY_NUM_LOCK)
{
// NumLock on: map to numeric keys
std::map<int, int>::iterator numPadIter = numlockKeyMap.find(key);
if (numPadIter != numlockKeyMap.end()) {
key = numPadIter->second;
}
#endif
}
else
{
// NumLock off: map to PU arrow keys
std::map<int, int>::iterator numPadIter = noNumlockKeyMap.find(key);
if (numPadIter != noNumlockKeyMap.end()) {
key = numPadIter->second;
}
}
#endif
modifiers = osgToFGModifiers(ea.getModKeyMask());
currentModifiers = modifiers;

View file

@ -113,6 +113,7 @@ protected:
int statsType;
int currentModifiers;
std::map<int, int> numlockKeyMap;
std::map<int, int> noNumlockKeyMap;
void handleKey(const osgGA::GUIEventAdapter& ea, int& key, int& modifiers);
bool resizable;
bool mouseWarped;

View file

@ -28,8 +28,12 @@
#include <stdio.h>
#include <string.h>
#include <osg/Camera>
#include <osg/Transform>
#include <osg/MatrixTransform>
#include <osg/PositionAttitudeTransform>
#include <osg/CameraView>
#include <osgViewer/Viewer>
#include <osgUtil/IntersectVisitor>
#include <simgear/constants.h>
#include <simgear/debug/logstream.hxx>
@ -38,6 +42,8 @@
#include <simgear/scene/util/SGNodeMasks.hxx>
#include <simgear/scene/util/SGSceneUserData.hxx>
#include <simgear/scene/model/CheckSceneryVisitor.hxx>
#include <simgear/scene/bvh/BVHNode.hxx>
#include <simgear/scene/bvh/BVHLineSegmentVisitor.hxx>
#include <Main/renderer.hxx>
#include <Main/fg_props.hxx>
@ -70,6 +76,138 @@ public:
}
};
class FGSceneryIntersect : public osg::NodeVisitor {
public:
FGSceneryIntersect(const SGLineSegmentd& lineSegment,
const osg::Node* skipNode) :
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN),
_lineSegment(lineSegment),
_skipNode(skipNode),
_material(0),
_haveHit(false)
{ }
bool getHaveHit() const
{ return _haveHit; }
const SGLineSegmentd& getLineSegment() const
{ return _lineSegment; }
const SGMaterial* getMaterial() const
{ return _material; }
virtual void apply(osg::Node& node)
{
if (&node == _skipNode)
return;
if (!testBoundingSphere(node.getBound()))
return;
addBoundingVolume(node);
}
virtual void apply(osg::Group& group)
{
if (&group == _skipNode)
return;
if (!testBoundingSphere(group.getBound()))
return;
traverse(group);
addBoundingVolume(group);
}
virtual void apply(osg::Transform& transform)
{ handleTransform(transform); }
virtual void apply(osg::Camera& camera)
{
if (camera.getRenderOrder() != osg::Camera::NESTED_RENDER)
return;
handleTransform(camera);
}
virtual void apply(osg::CameraView& transform)
{ handleTransform(transform); }
virtual void apply(osg::MatrixTransform& transform)
{ handleTransform(transform); }
virtual void apply(osg::PositionAttitudeTransform& transform)
{ handleTransform(transform); }
private:
void handleTransform(osg::Transform& transform)
{
if (&transform == _skipNode)
return;
// Hmm, may be this needs to be refined somehow ...
if (transform.getReferenceFrame() != osg::Transform::RELATIVE_RF)
return;
if (!testBoundingSphere(transform.getBound()))
return;
osg::Matrix inverseMatrix;
if (!transform.computeWorldToLocalMatrix(inverseMatrix, this))
return;
osg::Matrix matrix;
if (!transform.computeLocalToWorldMatrix(matrix, this))
return;
SGLineSegmentd lineSegment = _lineSegment;
bool haveHit = _haveHit;
const SGMaterial* material = _material;
_haveHit = false;
_lineSegment = lineSegment.transform(SGMatrixd(inverseMatrix.ptr()));
addBoundingVolume(transform);
traverse(transform);
if (_haveHit) {
_lineSegment = _lineSegment.transform(SGMatrixd(matrix.ptr()));
} else {
_lineSegment = lineSegment;
_material = material;
_haveHit = haveHit;
}
}
simgear::BVHNode* getNodeBoundingVolume(osg::Node& node)
{
SGSceneUserData* userData = SGSceneUserData::getSceneUserData(&node);
if (!userData)
return 0;
return userData->getBVHNode();
}
void addBoundingVolume(osg::Node& node)
{
simgear::BVHNode* bvNode = getNodeBoundingVolume(node);
if (!bvNode)
return;
// Find ground intersection on the bvh nodes
simgear::BVHLineSegmentVisitor lineSegmentVisitor(_lineSegment,
0/*startTime*/);
bvNode->accept(lineSegmentVisitor);
if (!lineSegmentVisitor.empty()) {
_lineSegment = lineSegmentVisitor.getLineSegment();
_material = lineSegmentVisitor.getMaterial();
_haveHit = true;
}
}
bool testBoundingSphere(const osg::BoundingSphere& bound) const
{
if (!bound.valid())
return false;
SGSphered sphere(toVec3d(toSG(bound._center)), bound._radius);
return intersects(_lineSegment, sphere);
}
SGLineSegmentd _lineSegment;
const osg::Node* _skipNode;
const SGMaterial* _material;
bool _haveHit;
};
// Scenery Management system
FGScenery::FGScenery()
{
@ -138,43 +276,20 @@ FGScenery::get_elevation_m(const SGGeod& geod, double& alt,
SGGeod geodEnd = geod;
geodEnd.setElevationM(SGMiscd::min(geod.getElevationM() - 10, -10000));
SGVec3d end = SGVec3d::fromGeod(geodEnd);
osgUtil::IntersectVisitor intersectVisitor;
FGSceneryIntersect intersectVisitor(SGLineSegmentd(start, end), butNotFrom);
intersectVisitor.setTraversalMask(SG_NODEMASK_TERRAIN_BIT);
osg::ref_ptr<osg::LineSegment> lineSegment;
lineSegment = new osg::LineSegment(toOsg(start), toOsg(end));
intersectVisitor.addLineSegment(lineSegment.get());
get_scene_graph()->accept(intersectVisitor);
bool hits = false;
if (intersectVisitor.hits()) {
int nHits = intersectVisitor.getNumHits(lineSegment.get());
alt = -SGLimitsd::max();
for (int i = 0; i < nHits; ++i) {
const osgUtil::Hit& hit
= intersectVisitor.getHitList(lineSegment.get())[i];
if (butNotFrom &&
std::find(hit.getNodePath().begin(), hit.getNodePath().end(),
butNotFrom) != hit.getNodePath().end())
continue;
// We might need the double variant of the intersection point.
// Thus we cannot use the float variant delivered by
// hit.getWorldIntersectPoint() but we have to redo that with osg::Vec3d.
osg::Vec3d point = hit.getLocalIntersectPoint();
if (hit.getMatrix())
point = point*(*hit.getMatrix());
SGGeod geod = SGGeod::fromCart(toSG(point));
double elevation = geod.getElevationM();
if (alt < elevation) {
alt = elevation;
hits = true;
if (material)
*material = SGMaterialLib::findMaterial(hit.getGeode());
}
}
}
if (!intersectVisitor.getHaveHit())
return false;
return hits;
geodEnd = SGGeod::fromCart(intersectVisitor.getLineSegment().getEnd());
alt = geodEnd.getElevationM();
if (material)
*material = intersectVisitor.getMaterial();
return true;
}
bool
@ -190,40 +305,16 @@ FGScenery::get_cart_ground_intersection(const SGVec3d& pos, const SGVec3d& dir,
// computation of ground intersection.
SGVec3d start = pos;
SGVec3d end = start + 1e5*normalize(dir); // FIXME visibility ???
osgUtil::IntersectVisitor intersectVisitor;
intersectVisitor.setTraversalMask(SG_NODEMASK_TERRAIN_BIT);
osg::ref_ptr<osg::LineSegment> lineSegment;
lineSegment = new osg::LineSegment(toOsg(start), toOsg(end));
intersectVisitor.addLineSegment(lineSegment.get());
get_scene_graph()->accept(intersectVisitor);
bool hits = false;
if (intersectVisitor.hits()) {
int nHits = intersectVisitor.getNumHits(lineSegment.get());
double dist = SGLimitsd::max();
for (int i = 0; i < nHits; ++i) {
const osgUtil::Hit& hit
= intersectVisitor.getHitList(lineSegment.get())[i];
if (butNotFrom &&
std::find(hit.getNodePath().begin(), hit.getNodePath().end(),
butNotFrom) != hit.getNodePath().end())
continue;
// We might need the double variant of the intersection point.
// Thus we cannot use the float variant delivered by
// hit.getWorldIntersectPoint() but we have to redo that with osg::Vec3d.
osg::Vec3d point = hit.getLocalIntersectPoint();
if (hit.getMatrix())
point = point*(*hit.getMatrix());
double newdist = length(start - toSG(point));
if (newdist < dist) {
dist = newdist;
nearestHit = toSG(point);
hits = true;
}
}
}
return hits;
FGSceneryIntersect intersectVisitor(SGLineSegmentd(start, end), butNotFrom);
intersectVisitor.setTraversalMask(SG_NODEMASK_TERRAIN_BIT);
get_scene_graph()->accept(intersectVisitor);
if (!intersectVisitor.getHaveHit())
return false;
nearestHit = intersectVisitor.getLineSegment().getEnd();
return true;
}
bool FGScenery::scenery_available(const SGGeod& position, double range_m)

View file

@ -24,14 +24,12 @@
#include <iostream>
#include <string>
#include <set>
#include <sys/stat.h>
#ifdef _WIN32
# include <direct.h>
#endif
#include <FL/Fl_File_Chooser.H>
#include <plib/ul.h>
#include <simgear/misc/sg_path.hxx>
@ -142,11 +140,12 @@ void FGAdminUI::update_install_box() {
install_box->clear();
if ( source.length() ) {
ulDir *dir = ulOpenDir( source.c_str() ) ;
ulDirEnt *ent;
while ( dir != 0 && ( ent = ulReadDir( dir ) ) ) {
struct dirent **list;
int nb = fl_filename_list( source.c_str(), &list );
for ( int i = 0; i < nb; ++i ) {
// find base name of archive file
char base[FL_PATH_MAX];
dirent *ent = list[i];
strncpy( base, ent->d_name, FL_PATH_MAX );
const char *p = fl_filename_ext( base );
int offset, expected_length = 0;
@ -186,9 +185,10 @@ void FGAdminUI::update_install_box() {
// cout << install.str() << " exists." << endl;
}
}
free( ent );
}
free( list );
ulCloseDir( dir );
for ( set<string>::iterator it = file_list.begin(); it != file_list.end(); ++it ) {
install_box->add( it->c_str() );
}
@ -217,16 +217,18 @@ void FGAdminUI::update_remove_box() {
set<string> dir_list;
for ( int i = 0; i < 2; i++ ) {
if ( !path[i].empty() ) {
ulDir *dir = ulOpenDir( path[i].c_str() ) ;
ulDirEnt *ent;
while ( dir != 0 && ( ent = ulReadDir( dir ) ) ) {
dirent **list;
int nb = fl_filename_list( path[i].c_str(), &list );
for ( int i = 0; i < nb; ++i ) {
dirent *ent = list[i];
if ( strlen(ent->d_name) == 7 &&
( ent->d_name[0] == 'e' || ent->d_name[0] == 'w' ) &&
( ent->d_name[4] == 'n' || ent->d_name[4] == 's' ) ) {
dir_list.insert( ent->d_name );
}
free( ent );
}
ulCloseDir( dir );
free( list );
}
}
@ -254,7 +256,7 @@ void FGAdminUI::install_selected() {
SGPath file( source );
file.append( f );
struct stat info;
stat( file.str().c_str(), &info );
fl_stat( file.str().c_str(), &info );
float old_max = progress->maximum();
progress->maximum( info.st_size );
progress_label = "Installing ";
@ -279,23 +281,25 @@ void FGAdminUI::install_selected() {
static unsigned long count_dir( const char *dir_name, bool top = true ) {
unsigned long cnt = 0L;
ulDir *dir = ulOpenDir( dir_name ) ;
if ( dir ) {
ulDirEnt *ent;
while ( ent = ulReadDir( dir ) ) {
dirent **list;
int nb = fl_filename_list( dir_name, &list );
if ( nb != 0 ) {
for ( int i = 0; i < nb; ++i ) {
dirent *ent = list[i];
if ( strcmp( ent->d_name, "." ) == 0 ) {
// ignore "."
} else if ( strcmp( ent->d_name, ".." ) == 0 ) {
// ignore ".."
} else if ( ent->d_isdir ) {
} else if ( fl_filename_isdir( ent->d_name ) ) {
SGPath child( dir_name );
child.append( ent->d_name );
cnt += count_dir( child.c_str(), false );
} else {
cnt += 1;
}
free( ent );
}
ulCloseDir( dir );
free( list );
} else if ( top ) {
string base = dir_name;
size_t pos = base.rfind('/');
@ -310,15 +314,16 @@ static unsigned long count_dir( const char *dir_name, bool top = true ) {
}
static void remove_dir( const char *dir_name, void (*step)(void*,int), void *data, bool top = true ) {
ulDir *dir = ulOpenDir( dir_name ) ;
if ( dir ) {
ulDirEnt *ent;
while ( ent = ulReadDir( dir ) ) {
dirent **list;
int nb = fl_filename_list( dir_name, &list );
if ( nb != 0 ) {
for ( int i = 0; i < nb; ++i ) {
dirent *ent = list[i];
if ( strcmp( ent->d_name, "." ) == 0 ) {
// ignore "."
} else if ( strcmp( ent->d_name, ".." ) == 0 ) {
// ignore ".."
} else if ( ent->d_isdir ) {
} else if ( fl_filename_isdir( ent->d_name ) ) {
SGPath child( dir_name );
child.append( ent->d_name );
remove_dir( child.c_str(), step, data, false );
@ -328,8 +333,9 @@ static void remove_dir( const char *dir_name, void (*step)(void*,int), void *dat
unlink( child.c_str() );
if (step) step( data, 1 );
}
free( ent );
}
ulCloseDir( dir );
free( list );
rmdir( dir_name );
} else if ( top ) {
string base = dir_name;

View file

@ -441,6 +441,8 @@ sub serve()
$metar .= sprintf "$icao %02d%02d%02dZ ", $day, $hour, $min;
$metar .= $last_metar{$addr} || $METAR_DEFAULT;
}
print $client "HTTP/1.0 200 OK\015\012";
print $client "Content-Type: text/plain\015\012"
. "X-MetarProxy: nasse Maus\015\012"
. "\015\012"