#include <osgUtil/SceneView>
#include <osgUtil/UpdateVisitor>
#include <osgUtil/IntersectVisitor>
+#include <osgUtil/LineSegmentIntersector>
#include <osg/io_utils>
#include <osgDB/WriteFile>
#include <Model/modelmgr.hxx>
#include <Model/acmodel.hxx>
#include <Scenery/scenery.hxx>
+#include <Scenery/redout.hxx>
#include <Scenery/tilemgr.hxx>
-#include <ATC/ATCdisplay.hxx>
#include <GUI/new_gui.hxx>
#include <Instrumentation/instrument_mgr.hxx>
#include <Instrumentation/HUD/HUD.hxx>
stateSet->setMode(GL_FOG, osg::StateAttribute::OFF);
stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
}
- virtual void drawImplementation(osg::State& state) const
+ virtual void drawImplementation(osg::RenderInfo& renderInfo) const
+ { drawImplementation(*renderInfo.getState()); }
+ void drawImplementation(osg::State& state) const
{
+ if (!fgOSIsMainContext(state.getGraphicsContext()))
+ return;
+
state.pushStateSet(getStateSet());
state.apply();
state.setActiveTextureUnit(0);
state.setClientActiveTextureUnit(0);
state.disableAllVertexArrays();
- if((fgGetBool("/sim/atc/enabled"))
- || (fgGetBool("/sim/ai-traffic/enabled")))
- globals->get_ATC_display()->update(delta_time_sec, state);
+ glPushAttrib(GL_ALL_ATTRIB_BITS);
+ glPushClientAttrib(~0u);
puDisplay();
- // Fade out the splash screen over the first three seconds.
- double t = globals->get_sim_time_sec();
- if (t <= 2.5) {
- glPushAttrib(GL_ALL_ATTRIB_BITS);
- glPushClientAttrib(~0u);
-
- fgSplashUpdate((2.5 - t) / 2.5);
-
- glPopClientAttrib();
- glPopAttrib();
- }
+ glPopClientAttrib();
+ glPopAttrib();
state.popStateSet();
state.dirtyAllModes();
stateSet->setTextureAttribute(0, new osg::TexEnv(osg::TexEnv::MODULATE));
}
- virtual void drawImplementation(osg::State& state) const
+ virtual void drawImplementation(osg::RenderInfo& renderInfo) const
+ { drawImplementation(*renderInfo.getState()); }
+ void drawImplementation(osg::State& state) const
{
+// std::cout << state.getGraphicsContext() << std::endl;
+ if (!fgOSIsMainContext(state.getGraphicsContext()))
+ return;
+
state.pushStateSet(getStateSet());
state.apply();
state.setActiveTextureUnit(0);
SGSharedPtr<SGPropertyNode> mFogEnabled;
};
-// fog constants. I'm a little nervous about putting actual code out
-// here but it seems to work (?)
-static const double m_log01 = -log( 0.01 );
-static const double sqrt_m_log01 = sqrt( m_log01 );
-static GLfloat fog_exp_density;
-static GLfloat fog_exp2_density;
-static GLfloat rwy_exp2_punch_through;
-static GLfloat taxi_exp2_punch_through;
-static GLfloat ground_exp2_punch_through;
+class FGFogUpdateCallback : public osg::StateAttribute::Callback {
+public:
+ virtual void operator () (osg::StateAttribute* sa, osg::NodeVisitor* nv)
+ {
+ assert(dynamic_cast<SGUpdateVisitor*>(nv));
+ assert(dynamic_cast<osg::Fog*>(sa));
+ SGUpdateVisitor* updateVisitor = static_cast<SGUpdateVisitor*>(nv);
+ osg::Fog* fog = static_cast<osg::Fog*>(sa);
+ fog->setMode(osg::Fog::EXP2);
+ fog->setColor(updateVisitor->getFogColor().osg());
+ fog->setDensity(updateVisitor->getFogExp2Density());
+ }
+};
+
+// update callback for the switch node guarding that splash
+class FGScenerySwitchCallback : public osg::NodeCallback {
+public:
+ virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
+ {
+ assert(dynamic_cast<osg::Switch*>(node));
+ osg::Switch* sw = static_cast<osg::Switch*>(node);
+
+ double t = globals->get_sim_time_sec();
+ bool enabled = 0 < t;
+ sw->setValue(0, enabled);
+ if (!enabled)
+ return;
+ traverse(node, nv);
+ }
+};
// Sky structures
SGSky *thesky;
static osg::ref_ptr<osg::FrameStamp> mFrameStamp = new osg::FrameStamp;
static osg::ref_ptr<SGUpdateVisitor> mUpdateVisitor= new SGUpdateVisitor;
+static osg::ref_ptr<osg::Group> mRealRoot = new osg::Group;
+
static osg::ref_ptr<osg::Group> mRoot = new osg::Group;
static osg::ref_ptr<osg::CameraView> mCameraView = new osg::CameraView;
static osg::ref_ptr<osg::Camera> mBackGroundCamera = new osg::Camera;
-static osg::ref_ptr<osg::Fog> mFog = new osg::Fog;
-static osg::ref_ptr<osg::Fog> mRunwayLightingFog = new osg::Fog;
-static osg::ref_ptr<osg::Fog> mTaxiLightingFog = new osg::Fog;
-static osg::ref_ptr<osg::Fog> mGroundLightingFog = new osg::Fog;
-
FGRenderer::FGRenderer()
{
#ifdef FG_JPEG_SERVER
jpgRenderFrame = FGRenderer::update;
#endif
+#ifdef ENABLE_OSGVIEWER
+ manipulator = new FGManipulator;
+#endif
}
FGRenderer::~FGRenderer()
}
// Initialize various GL/view parameters
+// XXX This should be called "preinit" or something, as it initializes
+// critical parts of the scene graph in addition to the splash screen.
void
-FGRenderer::init( void ) {
+FGRenderer::splashinit( void ) {
+ osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
+ if (viewer) {
+ sceneView = 0;
+ mRealRoot = dynamic_cast<osg::Group*>(viewer->getSceneData());
+ mRealRoot->addChild(fgCreateSplashNode());
+ osgViewer::Scene* scene = viewer->getScene();
+ mFrameStamp = viewer->getFrameStamp();
+ // Scene doesn't seem to pass the frame stamp to the update
+ // visitor automatically.
+ mUpdateVisitor->setFrameStamp(mFrameStamp.get());
+ scene->setUpdateVisitor(mUpdateVisitor.get());
+ } else {
+ // Add the splash screen node
+ mRealRoot->addChild(fgCreateSplashNode());
+ sceneView->setSceneData(mRealRoot.get());
+ sceneView->setDefaults(osgUtil::SceneView::COMPILE_GLOBJECTS_AT_INIT);
+ sceneView->setFrameStamp(mFrameStamp.get());
+ sceneView->setUpdateVisitor(mUpdateVisitor.get());
+ }
+}
+void
+FGRenderer::init( void ) {
+ // The viewer can call this before the graphics context is current
+ // in the main thread; indeed, in a multithreaded setup it might
+ // never be current in the main thread.
+ fgMakeCurrent();
+ osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
osg::initNotifyLevel();
// The number of polygon-offset "units" to place between layers. In
glHint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE);
glHint(GL_POINT_SMOOTH_HINT, GL_DONT_CARE);
- sceneView->setDefaults(osgUtil::SceneView::COMPILE_GLOBJECTS_AT_INIT);
-
- mFog->setMode(osg::Fog::EXP2);
- mRunwayLightingFog->setMode(osg::Fog::EXP2);
- mTaxiLightingFog->setMode(osg::Fog::EXP2);
- mGroundLightingFog->setMode(osg::Fog::EXP2);
-
- sceneView->setFrameStamp(mFrameStamp.get());
-
- mUpdateVisitor = new SGUpdateVisitor;
- sceneView->setUpdateVisitor(mUpdateVisitor.get());
-
- sceneView->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
- sceneView->getCamera()->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
+ if (viewer) {
+ viewer->getCamera()
+ ->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
+ } else {
+ sceneView->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
+ sceneView->getCamera()->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
+ }
osg::StateSet* stateSet = mRoot->getOrCreateStateSet();
stateSet->setAttributeAndModes(polygonMode);
// scene fog handling
- stateSet->setAttributeAndModes(mFog.get());
+ osg::Fog* fog = new osg::Fog;
+ fog->setUpdateCallback(new FGFogUpdateCallback);
+ stateSet->setAttributeAndModes(fog);
stateSet->setUpdateCallback(new FGFogEnableUpdateCallback);
// plug in the GUI
osg::Camera* guiCamera = new osg::Camera;
- guiCamera->setRenderOrder(osg::Camera::POST_RENDER);
+ guiCamera->setRenderOrder(osg::Camera::POST_RENDER, 100);
guiCamera->setClearMask(0);
inheritanceMask = osg::CullSettings::ALL_VARIABLES;
inheritanceMask &= ~osg::CullSettings::COMPUTE_NEAR_FAR_MODE;
guiCamera->setInheritanceMask(inheritanceMask);
guiCamera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
guiCamera->setCullingMode(osg::CullSettings::NO_CULLING);
- mRoot->addChild(guiCamera);
osg::Geode* geode = new osg::Geode;
geode->addDrawable(new SGPuDrawable);
geode->addDrawable(new SGHUDAndPanelDrawable);
guiCamera->addChild(geode);
- // this one contains all lights, here we set the light states we did
- // in the plib case with plain OpenGL
- osg::Group* lightGroup = new osg::Group;
- sceneGroup->addChild(lightGroup);
- lightGroup->addChild(globals->get_scenery()->get_gnd_lights_root());
- lightGroup->addChild(globals->get_scenery()->get_vasi_lights_root());
- lightGroup->addChild(globals->get_scenery()->get_rwy_lights_root());
- lightGroup->addChild(globals->get_scenery()->get_taxi_lights_root());
-
- stateSet = globals->get_scenery()->get_gnd_lights_root()->getOrCreateStateSet();
- stateSet->setAttributeAndModes(mFog.get());
- stateSet->setUpdateCallback(new FGFogEnableUpdateCallback);
- stateSet = globals->get_scenery()->get_vasi_lights_root()->getOrCreateStateSet();
- stateSet->setAttributeAndModes(mRunwayLightingFog.get());
- stateSet->setUpdateCallback(new FGFogEnableUpdateCallback);
- stateSet = globals->get_scenery()->get_rwy_lights_root()->getOrCreateStateSet();
- stateSet->setAttributeAndModes(mRunwayLightingFog.get());
- stateSet->setUpdateCallback(new FGFogEnableUpdateCallback);
- stateSet = globals->get_scenery()->get_taxi_lights_root()->getOrCreateStateSet();
- stateSet->setAttributeAndModes(mTaxiLightingFog.get());
- stateSet->setUpdateCallback(new FGFogEnableUpdateCallback);
-
mCameraView->addChild(mRoot.get());
- sceneView->setSceneData(mCameraView.get());
+ osg::Switch* sw = new osg::Switch;
+ sw->setUpdateCallback(new FGScenerySwitchCallback);
+ sw->addChild(mCameraView.get());
+
+ mRealRoot->addChild(sw);
+ mRealRoot->addChild(FGCreateRedoutNode());
+ mRealRoot->addChild(guiCamera);
// sceneView->getState()->setCheckForGLErrors(osg::State::ONCE_PER_ATTRIBUTE);
}
FGRenderer::update( bool refresh_camera_settings ) {
bool scenery_loaded = fgGetBool("sim/sceneryloaded")
|| fgGetBool("sim/sceneryloaded-override");
-
+ osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
if ( idle_state < 1000 || !scenery_loaded ) {
- if (sceneView.valid() && sceneView->getState()) {
- sceneView->getState()->setActiveTextureUnit(0);
- sceneView->getState()->setClientActiveTextureUnit(0);
- sceneView->getState()->disableAllVertexArrays();
- }
- // still initializing, draw the splash screen
- glPushAttrib(GL_ALL_ATTRIB_BITS);
- glPushClientAttrib(~0u);
-
- fgSplashUpdate(1.0);
-
- glPopClientAttrib();
- glPopAttrib();
+ fgSetDouble("/sim/startup/splash-alpha", 1.0);
// Keep resetting sim time while the sim is initializing
globals->set_sim_time_sec( 0.0 );
+
+ // the splash screen is now in the scenegraph
+ if (!viewer) {
+ sceneView->update();
+ sceneView->cull();
+ sceneView->draw();
+ }
return;
}
+ // Fade out the splash screen over the first three seconds.
+ double sAlpha = SGMiscd::max(0, (2.5 - globals->get_sim_time_sec()) / 2.5);
+ fgSetDouble("/sim/startup/splash-alpha", sAlpha);
+
bool skyblend = fgGetBool("/sim/rendering/skyblend");
bool use_point_sprites = fgGetBool("/sim/rendering/point-sprites");
bool enhanced_lighting = fgGetBool("/sim/rendering/enhanced-lighting");
actual_visibility = fgGetDouble("/environment/visibility-m");
}
- static double last_visibility = -9999;
- if ( actual_visibility != last_visibility ) {
- last_visibility = actual_visibility;
-
- fog_exp_density = m_log01 / actual_visibility;
- fog_exp2_density = sqrt_m_log01 / actual_visibility;
- ground_exp2_punch_through = sqrt_m_log01 / (actual_visibility * 1.5);
- if ( actual_visibility < 8000 ) {
- rwy_exp2_punch_through = sqrt_m_log01 / (actual_visibility * 2.5);
- taxi_exp2_punch_through = sqrt_m_log01 / (actual_visibility * 1.5);
- } else {
- rwy_exp2_punch_through = sqrt_m_log01 / ( 8000 * 2.5 );
- taxi_exp2_punch_through = sqrt_m_log01 / ( 8000 * 1.5 );
- }
- mFog->setDensity(fog_exp2_density);
- mRunwayLightingFog->setDensity(rwy_exp2_punch_through);
- mTaxiLightingFog->setDensity(taxi_exp2_punch_through);
- mGroundLightingFog->setDensity(ground_exp2_punch_through);
- }
-
// idle_state is now 1000 meaning we've finished all our
// initializations and are running the main loop, so this will
// now work without seg faulting the system.
resize( fgGetInt("/sim/startup/xsize"),
fgGetInt("/sim/startup/ysize") );
- SGVec3d center = globals->get_scenery()->get_center();
SGVec3d position = current__view->getViewPosition();
SGQuatd attitude = current__view->getViewOrientation();
- SGVec3d osgPosition = attitude.transform(center - position);
- mCameraView->setPosition(osgPosition.osg());
- mCameraView->setAttitude(inverse(attitude).osg());
+ SGVec3d osgPosition = attitude.transform(-position);
+ if (viewer) {
+ FGManipulator *manipulator
+ = globals->get_renderer()->getManipulator();
+ manipulator->setPosition(position.osg());
+ manipulator->setAttitude(attitude.osg());
+ } else {
+ mCameraView->setPosition(osgPosition.osg());
+ mCameraView->setAttitude(inverse(attitude).osg());
+ }
}
-
+ osg::Camera *camera;
+ if (viewer)
+ camera = viewer->getCamera();
+ else
+ camera = sceneView->getCamera();
if ( skyblend ) {
+
if ( fgGetBool("/sim/rendering/textures") ) {
SGVec4f clearColor(l->adj_fog_color());
- sceneView->getCamera()->setClearColor(clearColor.osg());
+ camera->setClearColor(clearColor.osg());
}
} else {
SGVec4f clearColor(l->sky_color());
- sceneView->getCamera()->setClearColor(clearColor.osg());
+ camera->setClearColor(clearColor.osg());
}
// update fog params if visibility has changed
static SGSkyState sstate;
- sstate.view_pos = current__view->get_view_pos();
- sstate.zero_elev = current__view->get_zero_elev();
+ sstate.view_pos = toVec3f(current__view->get_view_pos());
+ sstate.zero_elev = toVec3f(current__view->get_zero_elev());
sstate.view_up = current__view->get_world_up();
sstate.lon = current__view->getLongitude_deg()
* SGD_DEGREES_TO_RADIANS;
}
- if ( strcmp(fgGetString("/sim/rendering/fog"), "disabled") ) {
- SGVec4f color(l->adj_fog_color());
- mFog->setColor(color.osg());
- mRunwayLightingFog->setColor(color.osg());
- mTaxiLightingFog->setColor(color.osg());
- mGroundLightingFog->setColor(color.osg());
- }
-
-
// sgEnviro.setLight(l->adj_fog_color());
// texture parameters
// shadows->endOfFrame();
// need to call the update visitor once
- globals->get_aircraft_model()->select( true );
- FGTileMgr::set_tile_filter( true );
- mFrameStamp->setReferenceTime(globals->get_sim_time_sec());
- mFrameStamp->setFrameNumber(1+mFrameStamp->getFrameNumber());
+ if (!viewer) {
+ mFrameStamp->setReferenceTime(globals->get_sim_time_sec());
+ mFrameStamp->setSimulationTime(globals->get_sim_time_sec());
+ mFrameStamp->setFrameNumber(1+mFrameStamp->getFrameNumber());
+ }
mFrameStamp->setCalendarTime(*globals->get_time_params()->getGmt());
mUpdateVisitor->setViewData(current__view->getViewPosition(),
current__view->getViewOrientation());
- mUpdateVisitor->setSceneryCenter(globals->get_scenery()->get_center());
SGVec3f direction(l->sun_vec()[0], l->sun_vec()[1], l->sun_vec()[2]);
mUpdateVisitor->setLight(direction, l->scene_ambient(),
- l->scene_diffuse(), l->scene_specular());
+ l->scene_diffuse(), l->scene_specular(),
+ l->adj_fog_color(),
+ l->get_sun_angle()*SGD_RADIANS_TO_DEGREES);
mUpdateVisitor->setVisibility(actual_visibility);
-
- if (fgGetBool("/sim/panel-hotspots"))
- sceneView->setCullMask(sceneView->getCullMask()|SG_NODEMASK_PICK_BIT);
- else
- sceneView->setCullMask(sceneView->getCullMask()&(~SG_NODEMASK_PICK_BIT));
-
- sceneView->update();
- sceneView->cull();
- sceneView->draw();
+ bool hotspots = fgGetBool("/sim/panel-hotspots");
+ if (viewer) {
+ if (hotspots)
+ camera->setCullMask(camera->getCullMask()|SG_NODEMASK_PICK_BIT);
+ else
+ camera->setCullMask(camera->getCullMask()
+ & ~SG_NODEMASK_PICK_BIT);
+ } else {
+ if (hotspots)
+ sceneView->setCullMask(sceneView->getCullMask()
+ |SG_NODEMASK_PICK_BIT);
+ else
+ sceneView->setCullMask(sceneView->getCullMask()
+ &(~SG_NODEMASK_PICK_BIT));
+ sceneView->update();
+ sceneView->cull();
+ sceneView->draw();
+ }
}
} else {
view_h = height;
}
-
- sceneView->getViewport()->setViewport(0, height - view_h, width, view_h);
+ osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
+ if (viewer)
+ ;
+ // viewer->getCamera()->getViewport()->setViewport(0, height - view_h,
+// width, view_h);
+ else
+ sceneView->getViewport()->setViewport(0, height - view_h,
+ width, view_h);
static int lastwidth = 0;
static int lastheight = 0;
}
-// These are wrapper functions around ssgSetNearFar() and ssgSetFOV()
-// which will post process and rewrite the resulting frustum if we
-// want to do asymmetric view frustums.
-
-static void fgHackFrustum() {
-
- // specify a percent of the configured view frustum to actually
- // display. This is a bit of a hack to achieve asymmetric view
- // frustums. For instance, if you want to display two monitors
- // side by side, you could specify each with a double fov, a 0.5
- // aspect ratio multiplier, and then the left side monitor would
- // have a left_pct = 0.0, a right_pct = 0.5, a bottom_pct = 0.0,
- // and a top_pct = 1.0. The right side monitor would have a
- // left_pct = 0.5 and a right_pct = 1.0.
-
- static SGPropertyNode *left_pct
- = fgGetNode("/sim/current-view/frustum-left-pct");
- static SGPropertyNode *right_pct
- = fgGetNode("/sim/current-view/frustum-right-pct");
- static SGPropertyNode *bottom_pct
- = fgGetNode("/sim/current-view/frustum-bottom-pct");
- static SGPropertyNode *top_pct
- = fgGetNode("/sim/current-view/frustum-top-pct");
-
- double left, right;
- double bottom, top;
- double zNear, zFar;
- sceneView->getProjectionMatrixAsFrustum(left, right, bottom, top, zNear, zFar);
- // cout << " l = " << f->getLeft()
- // << " r = " << f->getRight()
- // << " b = " << f->getBot()
- // << " t = " << f->getTop()
- // << " n = " << f->getNear()
- // << " f = " << f->getFar()
- // << endl;
-
- double width = right - left;
- double height = top - bottom;
-
- double l, r, t, b;
-
- if ( left_pct != NULL ) {
- l = left + width * left_pct->getDoubleValue();
- } else {
- l = left;
- }
-
- if ( right_pct != NULL ) {
- r = left + width * right_pct->getDoubleValue();
- } else {
- r = right;
- }
-
- if ( bottom_pct != NULL ) {
- b = bottom + height * bottom_pct->getDoubleValue();
- } else {
- b = bottom;
- }
-
- if ( top_pct != NULL ) {
- t = bottom + height * top_pct->getDoubleValue();
- } else {
- t = top;
- }
-
- sceneView->setProjectionMatrixAsFrustum(l, r, b, t, zNear, zFar);
-}
-
-
// we need some static storage space for these values. However, we
// can't store it in a renderer class object because the functions
// that manipulate these are static. They are static so they can
void FGRenderer::setFOV( float w, float h ) {
fov_width = w;
fov_height = h;
-
- sceneView->setProjectionMatrixAsPerspective(fov_height,
- fov_width/fov_height,
- fov_near, fov_far);
- // fully specify the view frustum before hacking it (so we don't
- // accumulate hacked effects
- fgHackFrustum();
-// sgEnviro.setFOV( w, h );
+ osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
+ if (viewer)
+ viewer->getCamera()->setProjectionMatrixAsPerspective(fov_height, 4.0/3.0, fov_near, fov_far);
+ else
+ sceneView->setProjectionMatrixAsPerspective(fov_height,
+ fov_width/fov_height,
+ fov_near, fov_far);
}
n = 0.1;
fov_near = n;
fov_far = f;
+ osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
+ if (viewer)
+ viewer->getCamera()->setProjectionMatrixAsPerspective(fov_height, 4.0/3.0, fov_near, fov_far);
+ else
+ sceneView->setProjectionMatrixAsPerspective(fov_height,
+ fov_width/fov_height,
+ fov_near, fov_far);
- sceneView->setProjectionMatrixAsPerspective(fov_height,
- fov_width/fov_height,
- fov_near, fov_far);
-
- // fully specify the view frustum before hacking it (so we don't
- // accumulate hacked effects
- fgHackFrustum();
}
bool
FGRenderer::pick( unsigned x, unsigned y,
- std::vector<SGSceneryPick>& pickList )
+ std::vector<SGSceneryPick>& pickList,
+ const osgGA::GUIEventAdapter* ea )
{
+ osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
// wipe out the return ...
pickList.resize(0);
- // we can get called early ...
- if (!sceneView.valid())
- return false;
+ if (sceneView.valid()) {
+ osg::Node* sceneData = globals->get_scenery()->get_scene_graph();
+ if (!sceneData)
+ return false;
+
+ osg::Viewport* viewport = sceneView->getViewport();
+ if (!viewport)
+ return false;
+ // don't know why, but the update has partly happened somehow,
+ // so update the scenery part of the viewer
+ FGViewer *current_view = globals->get_current_view();
+ // Force update of center dependent values ...
+ current_view->set_dirty();
+ SGVec3d position = current_view->getViewPosition();
+ SGQuatd attitude = current_view->getViewOrientation();
+ SGVec3d osgPosition = attitude.transform(-position);
+ mCameraView->setPosition(osgPosition.osg());
+ mCameraView->setAttitude(inverse(attitude).osg());
+
+ osg::Matrix projection(sceneView->getProjectionMatrix());
+ osg::Matrix modelview(sceneView->getViewMatrix());
+
+ osg::NodePathList nodePath = sceneData->getParentalNodePaths();
+ // modify the view matrix so that it accounts for this nodePath's
+ // accumulated transform
+ if (!nodePath.empty())
+ modelview.preMult(computeLocalToWorld(nodePath.front()));
+
+ // swap the y values ...
+ y = viewport->height() - y;
+ // set up the pick visitor
+ osgUtil::PickVisitor pickVisitor(viewport, projection, modelview, x, y);
+ sceneData->accept(pickVisitor);
+ if (!pickVisitor.hits())
+ return false;
+
+ // collect all interaction callbacks on the pick ray.
+ // They get stored in the pickCallbacks list where they are sorted back
+ // to front and croasest to finest wrt the scenery node they are attached to
+ osgUtil::PickVisitor::LineSegmentHitListMap::const_iterator mi;
+ for (mi = pickVisitor.getSegHitList().begin();
+ mi != pickVisitor.getSegHitList().end();
+ ++mi) {
+ osgUtil::IntersectVisitor::HitList::const_iterator hi;
+ for (hi = mi->second.begin(); hi != mi->second.end(); ++hi) {
+ // ok, go back the nodes and ask for intersection callbacks,
+ // execute them in top down order
+ const osg::NodePath& np = hi->getNodePath();
+ osg::NodePath::const_reverse_iterator npi;
+ for (npi = np.rbegin(); npi != np.rend(); ++npi) {
+ SGSceneUserData* ud = SGSceneUserData::getSceneUserData(*npi);
+ if (!ud)
+ continue;
+ for (unsigned i = 0; i < ud->getNumPickCallbacks(); ++i) {
+ SGPickCallback* pickCallback = ud->getPickCallback(i);
+ if (!pickCallback)
+ continue;
+ SGSceneryPick sceneryPick;
+ /// note that this is done totally in doubles instead of
+ /// just using getWorldIntersectionPoint
+ osg::Vec3d localPt = hi->getLocalIntersectPoint();
+ sceneryPick.info.local = SGVec3d(localPt);
+ if (hi->getMatrix())
+ sceneryPick.info.wgs84 = SGVec3d(localPt*(*hi->getMatrix()));
+ else
+ sceneryPick.info.wgs84 = SGVec3d(localPt);
+ sceneryPick.callback = pickCallback;
+ pickList.push_back(sceneryPick);
+ }
+ }
+ }
+ }
+
+ return !pickList.empty();
- osg::Node* sceneData = globals->get_scenery()->get_scene_graph();
- if (!sceneData)
- return false;
- osg::Viewport* viewport = sceneView->getViewport();
- if (!viewport)
- return false;
+ } else if (viewer) {
- // good old scenery center
- SGVec3d center = globals->get_scenery()->get_center();
-
- // don't know why, but the update has partly happened somehow,
- // so update the scenery part of the viewer
- FGViewer *current_view = globals->get_current_view();
- // Force update of center dependent values ...
- current_view->set_dirty();
- SGVec3d position = current_view->getViewPosition();
- SGQuatd attitude = current_view->getViewOrientation();
- SGVec3d osgPosition = attitude.transform(center - position);
- mCameraView->setPosition(osgPosition.osg());
- mCameraView->setAttitude(inverse(attitude).osg());
-
- osg::Matrix projection(sceneView->getProjectionMatrix());
- osg::Matrix modelview(sceneView->getViewMatrix());
-
- osg::NodePathList nodePath = sceneData->getParentalNodePaths();
- // modify the view matrix so that it accounts for this nodePath's
- // accumulated transform
- if (!nodePath.empty())
- modelview.preMult(computeLocalToWorld(nodePath.front()));
-
- // swap the y values ...
- y = viewport->height() - y;
- // set up the pick visitor
- osgUtil::PickVisitor pickVisitor(viewport, projection, modelview, x, y);
- sceneData->accept(pickVisitor);
- if (!pickVisitor.hits())
- return false;
+ // just compute intersections in the viewers method ...
+ typedef osgUtil::LineSegmentIntersector::Intersections Intersections;
+ Intersections intersections;
+ viewer->computeIntersections(ea->getX(), ea->getY(), intersections);
- // collect all interaction callbacks on the pick ray.
- // They get stored in the pickCallbacks list where they are sorted back
- // to front and croasest to finest wrt the scenery node they are attached to
- osgUtil::PickVisitor::LineSegmentHitListMap::const_iterator mi;
- for (mi = pickVisitor.getSegHitList().begin();
- mi != pickVisitor.getSegHitList().end();
- ++mi) {
- osgUtil::IntersectVisitor::HitList::const_iterator hi;
- for (hi = mi->second.begin(); hi != mi->second.end(); ++hi) {
- // ok, go back the nodes and ask for intersection callbacks,
- // execute them in top down order
- const osg::NodePath& np = hi->getNodePath();
+ Intersections::iterator hit;
+ for (hit = intersections.begin(); hit != intersections.end(); ++hit) {
+ const osg::NodePath& np = hit->nodePath;
osg::NodePath::const_reverse_iterator npi;
for (npi = np.rbegin(); npi != np.rend(); ++npi) {
SGSceneUserData* ud = SGSceneUserData::getSceneUserData(*npi);
if (!pickCallback)
continue;
SGSceneryPick sceneryPick;
- /// note that this is done totally in doubles instead of
- /// just using getWorldIntersectionPoint
- osg::Vec3d localPt = hi->getLocalIntersectPoint();
- sceneryPick.info.local = SGVec3d(localPt);
- if (hi->getMatrix())
- sceneryPick.info.wgs84 = SGVec3d(localPt*(*hi->getMatrix()));
- else
- sceneryPick.info.wgs84 = SGVec3d(localPt);
- sceneryPick.info.wgs84 += globals->get_scenery()->get_center();
+ sceneryPick.info.local = SGVec3d(hit->getLocalIntersectPoint());
+ sceneryPick.info.wgs84 = SGVec3d(hit->getWorldIntersectPoint());
sceneryPick.callback = pickCallback;
pickList.push_back(sceneryPick);
}
}
}
+
+ return !pickList.empty();
+ } else { // we can get called early ...
+ return false;
}
+}
- return !pickList.empty();
+void
+FGRenderer::addCamera(osg::Camera* camera, bool useSceneData)
+{
+ mRealRoot->addChild(camera);
+}
+
+bool
+fgDumpSceneGraphToFile(const char* filename)
+{
+ return osgDB::writeNodeFile(*mRealRoot.get(), filename);
}
// end of renderer.cxx