X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FScenery%2Fscenery.cxx;h=26f49e4c932b5226ebe6dfe34e1a320f6eb1419c;hb=4fe615fff546df5e381f7fc9ddae92dd3dc36251;hp=ebd36caff6ca689b23d591f8cc18f905cece0872;hpb=43e48070fec3ff8299be0e6aa5a709711def50fe;p=flightgear.git diff --git a/src/Scenery/scenery.cxx b/src/Scenery/scenery.cxx index ebd36caff..26f49e4c9 100644 --- a/src/Scenery/scenery.cxx +++ b/src/Scenery/scenery.cxx @@ -2,7 +2,7 @@ // // Written by Curtis Olson, started May 1997. // -// Copyright (C) 1997 Curtis L. Olson - curt@infoplane.com +// Copyright (C) 1997 Curtis L. Olson - http://www.flightgear.org/~curt // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -16,7 +16,7 @@ // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software -// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // // $Id$ @@ -28,19 +28,46 @@ #include #include +#include + #include +#include +#include +#include +#include +#include +#include #include
#include "scenery.hxx" +class FGGroundPickCallback : public SGPickCallback { +public: + virtual bool buttonPressed(int button, const Info& info) + { + // only on left mouse button + if (button != 0) + return false; + + SGGeod geod = SGGeod::fromCart(info.wgs84); + SG_LOG( SG_TERRAIN, SG_INFO, "Got ground pick at " << geod ); + + SGPropertyNode *c = fgGetNode("/sim/input/click", true); + c->setDoubleValue("longitude-deg", geod.getLongitudeDeg()); + c->setDoubleValue("latitude-deg", geod.getLatitudeDeg()); + c->setDoubleValue("elevation-m", geod.getElevationM()); + c->setDoubleValue("elevation-ft", geod.getElevationFt()); + fgSetBool("/sim/signals/click", 1); + + return true; + } +}; // Scenery Management system -FGScenery::FGScenery() { +FGScenery::FGScenery() +{ SG_LOG( SG_TERRAIN, SG_INFO, "Initializing scenery subsystem" ); - - center = Point3D(0.0); - cur_elev = -9999; } @@ -51,31 +78,41 @@ FGScenery::~FGScenery() { void FGScenery::init() { // Scene graph root - scene_graph = new ssgRoot; + scene_graph = new osg::Group; scene_graph->setName( "Scene" ); // Terrain branch - terrain_branch = new ssgBranch; + terrain_branch = new osg::Group; terrain_branch->setName( "Terrain" ); - scene_graph->addKid( terrain_branch ); + scene_graph->addChild( terrain_branch.get() ); + SGSceneUserData* userData; + userData = SGSceneUserData::getOrCreateSceneUserData(terrain_branch.get()); + userData->setPickCallback(new FGGroundPickCallback); - models_branch = new ssgBranch; + models_branch = new osg::Group; models_branch->setName( "Models" ); - scene_graph->addKid( models_branch ); + scene_graph->addChild( models_branch.get() ); - aircraft_branch = new ssgBranch; + aircraft_branch = new osg::Group; aircraft_branch->setName( "Aircraft" ); - scene_graph->addKid( aircraft_branch ); + scene_graph->addChild( aircraft_branch.get() ); // Lighting - gnd_lights_root = new ssgRoot; + gnd_lights_root = new osg::Group; gnd_lights_root->setName( "Ground Lighting Root" ); - rwy_lights_root = new ssgRoot; + vasi_lights_root = new osg::Group; + vasi_lights_root->setName( "VASI/PAPI Lighting Root" ); + + rwy_lights_root = new osg::Group; rwy_lights_root->setName( "Runway Lighting Root" ); - taxi_lights_root = new ssgRoot; + taxi_lights_root = new osg::Group; taxi_lights_root->setName( "Taxi Lighting Root" ); + + // Initials values needed by the draw-time object loader + sgUserDataInit( globals->get_model_lib(), globals->get_fg_root(), + globals->get_props(), globals->get_sim_time_sec() ); } @@ -84,11 +121,96 @@ void FGScenery::update(double dt) { void FGScenery::bind() { - fgTie("/environment/ground-elevation-m", this, - &FGScenery::get_cur_elev, &FGScenery::set_cur_elev); } void FGScenery::unbind() { - fgUntie("/environment/ground-elevation-m"); +} + +bool +FGScenery::get_elevation_m(double lat, double lon, double max_alt, + double& alt, const SGMaterial** material, + bool exact) +{ + SGGeod geod = SGGeod::fromDegM(lon, lat, max_alt); + SGVec3d pos = SGVec3d::fromGeod(geod); + return get_cart_elevation_m(pos, 0, alt, material, exact); +} + +bool +FGScenery::get_cart_elevation_m(const SGVec3d& pos, double max_altoff, + double& alt, const SGMaterial** material, + bool exact) +{ + if ( norm1(pos) < 1 ) + return false; + + SGVec3d start = pos + max_altoff*normalize(pos); + SGVec3d end(0, 0, 0); + + osgUtil::IntersectVisitor intersectVisitor; + intersectVisitor.setTraversalMask(SG_NODEMASK_TERRAIN_BIT); + osg::ref_ptr lineSegment; + lineSegment = new osg::LineSegment(start.osg(), end.osg()); + intersectVisitor.addLineSegment(lineSegment.get()); + get_scene_graph()->accept(intersectVisitor); + bool hits = intersectVisitor.hits(); + if (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]; + SGVec3d point; + point.osg() = hit.getWorldIntersectPoint(); + SGGeod geod = SGGeod::fromCart(point); + double elevation = geod.getElevationM(); + if (alt < elevation) { + alt = elevation; + if (material) + *material = globals->get_matlib()->findMaterial(hit.getGeode()); + } + } + } + + return hits; +} + +bool +FGScenery::get_cart_ground_intersection(const SGVec3d& pos, const SGVec3d& dir, + SGVec3d& nearestHit, bool exact) +{ + // We assume that starting positions in the center of the earth are invalid + if ( norm1(pos) < 1 ) + return false; + + // Make really sure the direction is normalized, is really cheap compared to + // 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 lineSegment; + lineSegment = new osg::LineSegment(start.osg(), end.osg()); + intersectVisitor.addLineSegment(lineSegment.get()); + get_scene_graph()->accept(intersectVisitor); + bool hits = intersectVisitor.hits(); + if (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]; + SGVec3d point; + point.osg() = hit.getWorldIntersectPoint(); + double newdist = length(start - point); + if (newdist < dist) { + dist = newdist; + nearestHit = point; + } + } + } + + return hits; }