30#include <osg/Transform>
31#include <osg/MatrixTransform>
32#include <osg/PositionAttitudeTransform>
33#include <osg/CameraView>
35#include <osgTerrain/TerrainTile>
37#include <osgViewer/Viewer>
39#include <simgear/constants.h>
40#include <simgear/sg_inlines.h>
41#include <simgear/debug/logstream.hxx>
42#include <simgear/scene/tgdb/userdata.hxx>
43#include <simgear/scene/tgdb/VPBTechnique.hxx>
44#include <simgear/scene/material/matlib.hxx>
45#include <simgear/scene/material/mat.hxx>
46#include <simgear/scene/util/SGNodeMasks.hxx>
47#include <simgear/scene/util/OsgMath.hxx>
48#include <simgear/scene/util/SGSceneUserData.hxx>
49#include <simgear/scene/model/CheckSceneryVisitor.hxx>
50#include <simgear/scene/sky/sky.hxx>
52#include <simgear/bvh/BVHNode.hxx>
53#include <simgear/bvh/BVHLineSegmentVisitor.hxx>
54#include <simgear/bvh/BVHTerrainTile.hxx>
55#include <simgear/structure/commands.hxx>
72 const osgGA::GUIEventAdapter&,
79 SGGeod geod = SGGeod::fromCart(info.wgs84);
80 SG_LOG( SG_TERRAIN, SG_INFO,
"Got ground pick at " << geod );
82 SGPropertyNode *c =
fgGetNode(
"/sim/input/click",
true);
83 c->setDoubleValue(
"longitude-deg", geod.getLongitudeDeg());
84 c->setDoubleValue(
"latitude-deg", geod.getLatitudeDeg());
85 c->setDoubleValue(
"elevation-m", geod.getElevationM());
86 c->setDoubleValue(
"elevation-ft", geod.getElevationFt());
96 const osg::Node* skipNode) :
97 osg::NodeVisitor(
osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN),
98 _lineSegment(lineSegment),
107 {
return _lineSegment; }
109 {
return _material; }
113 if (&node == _skipNode)
115 if (!testBoundingSphere(node.getBound()))
118 addBoundingVolume(node);
121 virtual void apply(osg::Group& group)
123 if (&group == _skipNode)
125 if (!testBoundingSphere(group.getBound()))
129 addBoundingVolume(group);
131 if (_haveHit &&
dynamic_cast<osgTerrain::TerrainTile*
>(&group) && ! _material) {
134 osgTerrain::TerrainTile* tile =
dynamic_cast<osgTerrain::TerrainTile*
>(&group);
135 simgear::VPBTechnique* technique = tile ?
dynamic_cast<simgear::VPBTechnique*
>(tile->getTerrainTechnique()) : 0;
136 _material = technique ? technique->getMaterial(toOsg(_lineSegment.getEnd())) : 0;
140 virtual void apply(osg::Transform& transform)
141 { handleTransform(transform); }
142 virtual void apply(osg::Camera& camera)
144 if (camera.getRenderOrder() != osg::Camera::NESTED_RENDER)
146 handleTransform(camera);
148 virtual void apply(osg::CameraView& transform)
149 { handleTransform(transform); }
150 virtual void apply(osg::MatrixTransform& transform)
151 { handleTransform(transform); }
152 virtual void apply(osg::PositionAttitudeTransform& transform)
153 { handleTransform(transform); }
156 void handleTransform(osg::Transform& transform)
158 if (&transform == _skipNode)
161 if (transform.getReferenceFrame() != osg::Transform::RELATIVE_RF)
164 if (!testBoundingSphere(transform.getBound()))
167 osg::Matrix inverseMatrix;
168 if (!transform.computeWorldToLocalMatrix(inverseMatrix,
this))
171 if (!transform.computeLocalToWorldMatrix(matrix,
this))
174 SGLineSegmentd lineSegment = _lineSegment;
175 bool haveHit = _haveHit;
176 const simgear::BVHMaterial* material = _material;
179 _lineSegment = lineSegment.transform(SGMatrixd(inverseMatrix.ptr()));
181 addBoundingVolume(transform);
185 _lineSegment = _lineSegment.transform(SGMatrixd(matrix.ptr()));
187 _lineSegment = lineSegment;
188 _material = material;
193 simgear::BVHNode* getNodeBoundingVolume(osg::Node& node)
195 SGSceneUserData* userData = SGSceneUserData::getSceneUserData(&node);
198 return userData->getBVHNode();
200 void addBoundingVolume(osg::Node& node)
202 simgear::BVHNode* bvNode = getNodeBoundingVolume(node);
207 simgear::BVHLineSegmentVisitor lineSegmentVisitor(_lineSegment,
209 bvNode->accept(lineSegmentVisitor);
210 if (!lineSegmentVisitor.empty()) {
211 _lineSegment = lineSegmentVisitor.getLineSegment();
212 _material = lineSegmentVisitor.getMaterial();
217 bool testBoundingSphere(
const osg::BoundingSphere& bound)
const
222 SGSphered sphere(toVec3d(toSG(bound._center)), bound._radius);
223 return intersects(_lineSegment, sphere);
226 SGLineSegmentd _lineSegment;
227 const osg::Node* _skipNode;
229 const simgear::BVHMaterial* _material;
244 SG_LOG(SG_TERRAIN, SG_INFO,
"FGStgTerrain::dtor");
254 SG_LOG(SG_TERRAIN, SG_INFO,
"FGStgTerrain::init - init tilemgr");
257 terrain_branch = terrain;
268 SG_LOG(SG_TERRAIN, SG_INFO,
"FGStgTerrain::reinit - reinit tilemgr");
275 SG_LOG(SG_TERRAIN, SG_INFO,
"FGStgTerrain::shutdown - shutdown tilemgr");
279 terrain_branch = NULL;
293 SG_LOG(SG_TERRAIN, SG_INFO,
"FGStgTerrain::bind - noop");
298 SG_LOG(SG_TERRAIN, SG_INFO,
"FGStgTerrain::unbind - noop");
304 const simgear::BVHMaterial** material,
305 const osg::Node* butNotFrom)
309 SGGeod geod = SGGeod::fromCart(pos);
313 geod.setElevationM(geod.getElevationM() + max_altoff);
322 const simgear::BVHMaterial** material,
323 const osg::Node* butNotFrom)
328 SGVec3d start = SGVec3d::fromGeod(geod);
330 SGGeod geodEnd = geod;
331 geodEnd.setElevationM(SGMiscd::min(geod.getElevationM() - 10, -10000));
332 SGVec3d end = SGVec3d::fromGeod(geodEnd);
335 intersectVisitor.setTraversalMask(SG_NODEMASK_TERRAIN_BIT);
336 terrain_branch->accept(intersectVisitor);
341 geodEnd = SGGeod::fromCart(intersectVisitor.
getLineSegment().getEnd());
342 alt = geodEnd.getElevationM();
353 const osg::Node* butNotFrom)
356 if ( norm1(pos) < 1 )
362 SGVec3d end = start + 1e5*normalize(dir);
365 intersectVisitor.setTraversalMask(SG_NODEMASK_TERRAIN_BIT);
366 terrain_branch->accept(intersectVisitor);
381 bool use_vpb =
globals->get_props()->getNode(
"scenery/use-vpb")->getBoolValue();
382 bool got_elev =
get_elevation_m(SGGeod::fromGeodM(position, SG_MAX_ELEVATION_M), elev, 0, 0);
384 if (!use_vpb && !got_elev)
386 SG_LOG(SG_TERRAIN, SG_DEBUG,
"FGStgTerrain::scenery_available - false" );
390 SGVec3f
p = SGVec3f::fromGeod(SGGeod::fromGeodM(position, elev));
391 osg::FrameStamp* framestamp
392 =
globals->get_renderer()->getFrameStamp();
395 simgear::CheckSceneryVisitor csnv(pSceneryManager->
getPager(), toOsg(
p), range_m, framestamp);
399 terrain_branch->accept(csnv);
400 if(!csnv.isLoaded()) {
401 SG_LOG(SG_TERRAIN, SG_DEBUG,
"FGScenery::scenery_available: waiting on CheckSceneryVisitor");
405 SG_LOG(SG_TERRAIN, SG_DEBUG,
"FGStgTerrain::scenery_available - true" );
408 SG_LOG(SG_TERRAIN, SG_DEBUG,
"FGScenery::scenery_available: waiting on tile manager");
410 SG_LOG(SG_TERRAIN, SG_DEBUG,
"FGStgTerrain::scenery_available - false" );
416 SG_LOG(SG_TERRAIN, SG_BULK,
"FGStgTerrain::schedule_scenery");
418 return _tilemgr.schedule_scenery( position, range_m, duration );
423 _tilemgr.materialLibChanged();
virtual bool buttonPressed(int button, const osgGA::GUIEventAdapter &, const Info &info)
virtual void apply(osg::Camera &camera)
const simgear::BVHMaterial * getMaterial() const
virtual void apply(osg::Group &group)
virtual void apply(osg::Node &node)
FGSceneryIntersect(const SGLineSegmentd &lineSegment, const osg::Node *skipNode)
const SGLineSegmentd & getLineSegment() const
virtual void apply(osg::MatrixTransform &transform)
virtual void apply(osg::PositionAttitudeTransform &transform)
virtual void apply(osg::CameraView &transform)
virtual void apply(osg::Transform &transform)
flightgear::SceneryPager * getPager()
bool schedule_scenery(const SGGeod &position, double range_m, double duration=0.0)
bool get_elevation_m(const SGGeod &geod, double &alt, const simgear::BVHMaterial **material, const osg::Node *butNotFrom=0)
Compute the elevation of the scenery at geodetic latitude lat, geodetic longitude lon and not higher ...
bool scenery_available(const SGGeod &position, double range_m)
Returns true if scenery is available for the given lat, lon position within a range of range_m.
bool get_cart_elevation_m(const SGVec3d &pos, double max_altoff, double &elevation, const simgear::BVHMaterial **material, const osg::Node *butNotFrom=0)
Compute the elevation of the scenery below the cartesian point pos.
bool get_cart_ground_intersection(const SGVec3d &start, const SGVec3d &dir, SGVec3d &nearestHit, const osg::Node *butNotFrom=0)
Compute the nearest intersection point of the line starting from start going in direction dir with th...
void init(osg::Group *terrain)
void materialLibChanged()
FlightPlan.hxx - defines a full flight-plan object, including departure, cruise, arrival information ...
bool fgSetBool(char const *name, bool val)
Set a bool value for a property.
SGPropertyNode * fgGetNode(const char *path, bool create)
Get a property node.