#include <vector>
#include <typeinfo>
+#include <boost/foreach.hpp>
+
#include <osg/ref_ptr>
#include <osg/AlphaFunc>
#include <osg/BlendFunc>
#include <simgear/scene/material/EffectCullVisitor.hxx>
#include <simgear/scene/material/Effect.hxx>
#include <simgear/scene/material/EffectGeode.hxx>
+#include <simgear/scene/material/EffectBuilder.hxx>
#include <simgear/scene/model/animation.hxx>
#include <simgear/scene/model/placement.hxx>
#include <simgear/scene/sky/sky.hxx>
+#include <simgear/scene/util/DeletionManager.hxx>
#include <simgear/scene/util/SGUpdateVisitor.hxx>
#include <simgear/scene/util/RenderConstants.hxx>
#include <simgear/scene/util/SGSceneUserData.hxx>
#include <simgear/scene/tgdb/GroundLightManager.hxx>
#include <simgear/scene/tgdb/pt_lights.hxx>
+#include <simgear/scene/tgdb/userdata.hxx>
#include <simgear/structure/OSGUtils.hxx>
#include <simgear/props/props.hxx>
#include <simgear/timing/sg_time.hxx>
#include <simgear/ephemeris/ephemeris.hxx>
#include <simgear/math/sg_random.h>
-#ifdef FG_JPEG_SERVER
-#include <simgear/screen/jpgfactory.hxx>
-#endif
#include <Time/light.hxx>
#include <Time/light.hxx>
#include "CameraGroup.hxx"
#include "FGEventHandler.hxx"
+#include <plib/pu.h>
+
using namespace osg;
using namespace simgear;
using namespace flightgear;
glPushAttrib(GL_ALL_ATTRIB_BITS);
glPushClientAttrib(~0u);
- HUD *hud = static_cast<HUD*>(globals->get_subsystem("hud"));
- hud->draw(state);
-
+ // HUD can be NULL
+ HUD *hud = static_cast<HUD*>(globals->get_subsystem("hud"));
+ if (hud) {
+ hud->draw(state);
+ }
+
glPopClientAttrib();
glPopAttrib();
}
osg::Light* light = lightSource->getLight();
FGLight *l = static_cast<FGLight*>(globals->get_subsystem("lighting"));
+ if (!l) {
+ // lighting is down during re-init
+ return;
+ }
+
if (_isSun) {
light->setAmbient(Vec4(0.0f, 0.0f, 0.0f, 0.0f));
light->setDiffuse(Vec4(1.0f, 1.0f, 1.0f, 1.0f));
bool FGScenerySwitchCallback::scenery_enabled = false;
-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> mDeferredRealRoot = new osg::Group;
-
-static osg::ref_ptr<osg::Group> mRoot = new osg::Group;
-
-static osg::ref_ptr<osg::Switch> panelSwitch;
-
-
-// update callback for the switch node controlling the 2D panel
-class FGPanelSwitchCallback : 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);
-
- bool enabled = fgPanelVisible();
- sw->setValue(0, enabled);
- if (!enabled)
- return;
- traverse(node, nv);
- }
-};
-
-#ifdef FG_JPEG_SERVER
-static void updateRenderer()
-{
- globals->get_renderer()->update();
-}
-#endif
-
FGRenderer::FGRenderer() :
_sky(NULL),
_ambientFactor( new osg::Uniform( "fg_SunAmbientColor", osg::Vec4f() ) ),
_shadowDistances( new osg::Uniform( "fg_ShadowDistances", osg::Vec4f(5.0, 50.0, 500.0, 5000.0 ) ) ),
_depthInColor( new osg::Uniform( "fg_DepthInColor", false ) )
{
-#ifdef FG_JPEG_SERVER
- jpgRenderFrame = updateRenderer;
-#endif
- eventHandler = new FGEventHandler;
+ // it's not the real root, whatever that means
+ _root = new osg::Group;
+ _root->setName("fakeRoot");
+ _updateVisitor = new SGUpdateVisitor;
+
+ // when Rembrandt is enabled, we use this group to access the whole
+ // scene. Since the only child is the _viewerSceneRoot, we could
+ // simply copy the reference, we don't need the additional group.
+ _deferredRealRoot = new osg::Group;
+
_numCascades = 4;
_cascadeFar[0] = 5.f;
_cascadeFar[1] = 50.f;
FGRenderer::~FGRenderer()
{
-#ifdef FG_JPEG_SERVER
- jpgRenderFrame = NULL;
-#endif
+ SGPropertyChangeListenerVec::iterator i = _listeners.begin();
+ for (; i != _listeners.end(); ++i) {
+ delete *i;
+ }
+
+ // replace the viewer's scene completely
+ if (getViewer()) {
+ getViewer()->setSceneData(new osg::Group);
+ }
+
delete _sky;
}
// 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::splashinit( void ) {
+FGRenderer::splashinit( void )
+{
+ // important that we reset the viewer sceneData here, to ensure the reference
+ // time for everything is in sync; otherwise on reset the Viewer and
+ // GraphicsWindow clocks are out of sync.
osgViewer::Viewer* viewer = getViewer();
- mRealRoot = dynamic_cast<osg::Group*>(viewer->getSceneData());
+ viewer->setName("osgViewer");
+ _viewerSceneRoot = new osg::Group;
+ _viewerSceneRoot->setName("viewerSceneRoot");
+ viewer->setSceneData(_viewerSceneRoot);
+
ref_ptr<Node> splashNode = fgCreateSplashNode();
if (_classicalRenderer) {
- mRealRoot->addChild(splashNode.get());
+ _viewerSceneRoot->addChild(splashNode.get());
} else {
for ( CameraGroup::CameraIterator ii = CameraGroup::getDefault()->camerasBegin();
ii != CameraGroup::getDefault()->camerasEnd();
camera->addChild(splashNode.get());
}
}
- mFrameStamp = viewer->getFrameStamp();
+
+ _frameStamp = new osg::FrameStamp;
+ viewer->setFrameStamp(_frameStamp.get());
// Scene doesn't seem to pass the frame stamp to the update
// visitor automatically.
- mUpdateVisitor->setFrameStamp(mFrameStamp.get());
- viewer->setUpdateVisitor(mUpdateVisitor.get());
+ _updateVisitor->setFrameStamp(_frameStamp.get());
+ viewer->setUpdateVisitor(_updateVisitor.get());
fgSetDouble("/sim/startup/splash-alpha", 1.0);
}
}
};
+void
+FGRenderer::addChangeListener(SGPropertyChangeListener* l, const char* path)
+{
+ _listeners.push_back(l);
+ fgAddChangeListener(l, path);
+}
+
void
FGRenderer::init( void )
{
- _classicalRenderer = !fgGetBool("/sim/rendering/rembrandt", false);
+ if (!eventHandler)
+ eventHandler = new FGEventHandler();
+
+ sgUserDataInit( globals->get_props() );
+
+ _classicalRenderer = !fgGetBool("/sim/rendering/rembrandt/enabled", false);
_shadowMapSize = fgGetInt( "/sim/rendering/shadows/map-size", 4096 );
- fgAddChangeListener( new ShadowMapSizeListener, "/sim/rendering/shadows/map-size" );
- fgAddChangeListener( new ShadowEnabledListener, "/sim/rendering/shadows/enabled" );
+ addChangeListener( new ShadowMapSizeListener, "/sim/rendering/shadows/map-size" );
+ addChangeListener( new ShadowEnabledListener, "/sim/rendering/shadows/enabled" );
ShadowRangeListener* srl = new ShadowRangeListener;
- fgAddChangeListener(srl, "/sim/rendering/shadows/cascade-far-m[0]");
+ addChangeListener(srl, "/sim/rendering/shadows/cascade-far-m[0]");
fgAddChangeListener(srl, "/sim/rendering/shadows/cascade-far-m[1]");
fgAddChangeListener(srl, "/sim/rendering/shadows/cascade-far-m[2]");
fgAddChangeListener(srl, "/sim/rendering/shadows/cascade-far-m[3]");
- fgAddChangeListener(new ShadowNumListener, "/sim/rendering/shadows/num-cascades");
+ addChangeListener(new ShadowNumListener, "/sim/rendering/shadows/num-cascades");
_numCascades = fgGetInt("/sim/rendering/shadows/num-cascades", 4);
_cascadeFar[0] = fgGetFloat("/sim/rendering/shadows/cascade-far-m[0]", 5.0f);
_cascadeFar[1] = fgGetFloat("/sim/rendering/shadows/cascade-far-m[1]", 50.0f);
updateCascadeFar(1, _cascadeFar[1]);
updateCascadeFar(2, _cascadeFar[2]);
updateCascadeFar(3, _cascadeFar[3]);
- _useColorForDepth = fgGetBool( "/sim/rendering/use-color-for-depth", false );
+ _useColorForDepth = fgGetBool( "/sim/rendering/rembrandt/use-color-for-depth", false );
_depthInColor->set( _useColorForDepth );
+ _renderer = fgGetString("/sim/rendering/rembrandt/renderer", "default-pipeline");
+ if (!_classicalRenderer)
+ _pipeline = makeRenderingPipeline(_renderer, 0);
_scenery_loaded = fgGetNode("/sim/sceneryloaded", true);
- _scenery_override = fgGetNode("/sim/sceneryloaded-override", true);
+ _position_finalized = fgGetNode("/sim/position-finalized", true);
+
_panel_hotspots = fgGetNode("/sim/panel-hotspots", true);
_virtual_cockpit = fgGetNode("/sim/virtual-cockpit", true);
_ysize = fgGetNode("/sim/startup/ysize", true);
_splash_alpha = fgGetNode("/sim/startup/splash-alpha", true);
- _skyblend = fgGetNode("/sim/rendering/skyblend", true);
_point_sprites = fgGetNode("/sim/rendering/point-sprites", true);
_enhanced_lighting = fgGetNode("/sim/rendering/enhanced-lighting", true);
_distance_attenuation = fgGetNode("/sim/rendering/distance-attenuation", true);
_horizon_effect = fgGetNode("/sim/rendering/horizon-effect", true);
- _textures = fgGetNode("/sim/rendering/textures", true);
_altitude_ft = fgGetNode("/position/altitude-ft", true);
= static_cast<osgViewer::Renderer*>(camera->getRenderer());
for (int i = 0; i < 2; ++i) {
osgUtil::SceneView* sceneView = renderer->getSceneView(i);
-#if SG_OSG_VERSION_LESS_THAN(3,0,0)
- sceneView->setCullVisitor(new simgear::EffectCullVisitor);
-#else
+
osg::ref_ptr<osgUtil::CullVisitor::Identifier> identifier;
identifier = sceneView->getCullVisitor()->getIdentifier();
sceneView->setCullVisitor(new simgear::EffectCullVisitor);
identifier = sceneView->getCullVisitorRight()->getIdentifier();
sceneView->setCullVisitorRight(sceneView->getCullVisitor()->clone());
sceneView->getCullVisitorRight()->setIdentifier(identifier.get());
-#endif
+
}
}
-flightgear::CameraInfo*
-FGRenderer::buildRenderingPipeline(flightgear::CameraGroup* cgroup, unsigned flags, Camera* camera,
+CameraInfo*
+FGRenderer::buildRenderingPipeline(CameraGroup* cgroup, unsigned flags, Camera* camera,
const Matrix& view,
const Matrix& projection,
osg::GraphicsContext* gc,
bool useMasterSceneData)
{
- flightgear::CameraInfo* info = 0;
+ CameraInfo* info = 0;
if (!_classicalRenderer && (flags & (CameraGroup::GUI | CameraGroup::ORTHO)) == 0)
info = buildDeferredPipeline( cgroup, flags, camera, view, projection, gc );
}
}
-flightgear::CameraInfo*
-FGRenderer::buildClassicalPipeline(flightgear::CameraGroup* cgroup, unsigned flags, osg::Camera* camera,
+CameraInfo*
+FGRenderer::buildClassicalPipeline(CameraGroup* cgroup, unsigned flags, osg::Camera* camera,
const osg::Matrix& view,
const osg::Matrix& projection,
bool useMasterSceneData)
CameraInfo* info = new CameraInfo(flags);
// The camera group will always update the camera
camera->setReferenceFrame(Transform::ABSOLUTE_RF);
-
+ info->name = "classic";
+
Camera* farCamera = 0;
if ((flags & (CameraGroup::GUI | CameraGroup::ORTHO)) == 0) {
farCamera = new Camera;
+ farCamera->setName("farCamera");
farCamera->setAllowEventFocus(camera->getAllowEventFocus());
farCamera->setGraphicsContext(camera->getGraphicsContext());
farCamera->setCullingMode(camera->getCullingMode());
cgroup->getViewer()->addSlave(camera, projection, view, useMasterSceneData);
installCullVisitor(camera);
int slaveIndex = cgroup->getViewer()->getNumSlaves() - 1;
- info->addCamera( MAIN_CAMERA, camera, slaveIndex );
+ info->addCamera( MAIN_CAMERA, camera, slaveIndex );
camera->setRenderOrder(Camera::POST_RENDER, slaveIndex);
cgroup->addCamera(info);
return info;
class FGDeferredRenderingCameraCullCallback : public osg::NodeCallback {
public:
- FGDeferredRenderingCameraCullCallback( const std::string& k, CameraInfo* i ) : kind( k ), info( i ) {}
+ FGDeferredRenderingCameraCullCallback( const std::string& k, CameraInfo* i, bool nd = false ) : kind( k ), info( i ), needsDuDv(nd) {}
virtual void operator()( osg::Node *n, osg::NodeVisitor *nv) {
simgear::EffectCullVisitor* cv = dynamic_cast<simgear::EffectCullVisitor*>(nv);
osg::Camera* camera = static_cast<osg::Camera*>(n);
cv->clearBufferList();
- cv->addBuffer("depth", info->getBuffer( "depth" ) );
- cv->addBuffer("normal", info->getBuffer( "normal" ) );
- cv->addBuffer("diffuse", info->getBuffer( "diffuse" ) );
- cv->addBuffer("spec-emis", info->getBuffer( "spec-emis" ) );
- cv->addBuffer("lighting", info->getBuffer( "lighting" ) );
- cv->addBuffer("shadow", info->getBuffer( "shadow" ) );
- // cv->addBuffer(simgear::Effect::AO_BUFFER, info->gBuffer->aoBuffer[2]);
+ for (RenderBufferMap::iterator ii = info->buffers.begin(); ii != info->buffers.end(); ++ii) {
+ cv->addBuffer(ii->first, ii->second.texture);
+ }
if ( !info->getRenderStageInfo(kind).fullscreen )
info->setMatrices( camera );
+ if (needsDuDv) {
+ osg::Matrix projInverse;
+ info->projInverse->get( projInverse );
+
+ osg::Vec4 p0 = osg::Vec4( -1.0, -1.0, 0.0, 1.0 ) * projInverse;
+ info->du->set( osg::Vec4( 1.0, -1.0, 0.0, 1.0 ) * projInverse - p0 );
+ info->dv->set( osg::Vec4( -1.0, 1.0, 0.0, 1.0 ) * projInverse - p0 );
+ }
+
cv->traverse( *camera );
- if ( kind == flightgear::GEOMETRY_CAMERA ) {
- // Save transparent bins to render later
+ if ( kind == GEOMETRY_CAMERA ) {
+ // Remove transparent bins. They will be renderer in the additional light stage (side effect)
osgUtil::RenderStage* renderStage = cv->getRenderStage();
osgUtil::RenderBin::RenderBinList& rbl = renderStage->getRenderBinList();
for (osgUtil::RenderBin::RenderBinList::iterator rbi = rbl.begin(); rbi != rbl.end(); ) {
if (rbi->second->getSortMode() == osgUtil::RenderBin::SORT_BACK_TO_FRONT) {
- info->savedTransparentBins.insert( std::make_pair( rbi->first, rbi->second ) );
rbl.erase( rbi++ );
} else {
++rbi;
}
}
- } else if ( kind == flightgear::LIGHTING_CAMERA ) {
+ } else if ( kind == LIGHTING_CAMERA ) {
osg::ref_ptr<osg::Camera> mainShadowCamera = info->getCamera( SHADOW_CAMERA );
if (mainShadowCamera.valid()) {
osg::Switch* grp = mainShadowCamera->getChild(0)->asSwitch();
for (int i = 0; i < 4; ++i ) {
if (!grp->getValue(i))
continue;
- osg::TexGen* shadowTexGen = info->shadowTexGen[i];
- shadowTexGen->setMode(osg::TexGen::EYE_LINEAR);
osg::Camera* cascadeCam = static_cast<osg::Camera*>( grp->getChild(i) );
- // compute the matrix which takes a vertex from view coords into tex coords
- shadowTexGen->setPlanesFromMatrix( cascadeCam->getProjectionMatrix() *
- osg::Matrix::translate(1.0,1.0,1.0) *
- osg::Matrix::scale(0.5f,0.5f,0.5f) );
-
- osg::RefMatrix * refMatrix = new osg::RefMatrix( cascadeCam->getInverseViewMatrix() * *cv->getModelViewMatrix() );
+ osg::Matrixf shadowMatrix = camera->getInverseViewMatrix() *
+ cascadeCam->getViewMatrix() *
+ cascadeCam->getProjectionMatrix() *
+ osg::Matrix::translate(1.0, 1.0, 1.0) *
+ osg::Matrix::scale(0.5f, 0.5f, 0.5f);
- cv->getRenderStage()->getPositionalStateContainer()->addPositionedTextureAttribute( i+1, refMatrix, shadowTexGen );
+ info->shadowMatrix[i]->set( shadowMatrix );
}
}
- // Render saved transparent render bins
- osgUtil::RenderStage* renderStage = cv->getRenderStage();
- osgUtil::RenderBin::RenderBinList& rbl = renderStage->getRenderBinList();
- for (osgUtil::RenderBin::RenderBinList::iterator rbi = info->savedTransparentBins.begin(); rbi != info->savedTransparentBins.end(); ++rbi ){
- rbl.insert( std::make_pair( rbi->first + 10000, rbi->second ) );
- }
- info->savedTransparentBins.clear();
}
}
private:
std::string kind;
CameraInfo* info;
+ bool needsDuDv;
};
-osg::Texture2D* buildDeferredBuffer(GLint internalFormat, GLenum sourceFormat, GLenum sourceType, osg::Texture::WrapMode wrapMode, bool shadowComparison = false)
+osg::Texture2D* buildDeferredBuffer(GLint internalFormat, GLenum sourceFormat, GLenum sourceType, GLenum wrapMode, bool shadowComparison = false)
{
osg::Texture2D* tex = new osg::Texture2D;
tex->setResizeNonPowerOfTwoHint( false );
tex->setSourceType(sourceType);
tex->setFilter( osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR );
tex->setFilter( osg::Texture2D::MAG_FILTER, osg::Texture2D::LINEAR );
- tex->setWrap( osg::Texture::WRAP_S, wrapMode );
- tex->setWrap( osg::Texture::WRAP_T, wrapMode );
+ tex->setWrap( osg::Texture::WRAP_S, (osg::Texture::WrapMode)wrapMode );
+ tex->setWrap( osg::Texture::WRAP_T, (osg::Texture::WrapMode)wrapMode );
return tex;
}
-void buildDeferredBuffers( flightgear::CameraInfo* info, int shadowMapSize, bool useColorForDepth )
-{
- if (useColorForDepth) {
- info->addBuffer("real-depth", buildDeferredBuffer( GL_DEPTH_COMPONENT32, GL_DEPTH_COMPONENT, GL_FLOAT, osg::Texture::CLAMP_TO_BORDER) );
- info->addBuffer("depth", buildDeferredBuffer( GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, osg::Texture::CLAMP_TO_BORDER) );
- }
- else {
- info->addBuffer("depth", buildDeferredBuffer( GL_DEPTH_COMPONENT32, GL_DEPTH_COMPONENT, GL_FLOAT, osg::Texture::CLAMP_TO_BORDER) );
- }
- info->addBuffer("normal", buildDeferredBuffer( GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, osg::Texture::CLAMP_TO_BORDER) );
- info->addBuffer("diffuse", buildDeferredBuffer( GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, osg::Texture::CLAMP_TO_BORDER) );
- info->addBuffer("spec-emis", buildDeferredBuffer( GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, osg::Texture::CLAMP_TO_BORDER) );
- info->addBuffer("lighting", buildDeferredBuffer( GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, osg::Texture::CLAMP_TO_BORDER) );
- info->addBuffer("shadow", buildDeferredBuffer( GL_DEPTH_COMPONENT32, GL_DEPTH_COMPONENT, GL_FLOAT, osg::Texture::CLAMP_TO_BORDER, true), 0.0f );
- info->getBuffer("shadow")->setTextureSize(shadowMapSize,shadowMapSize);
-}
-
-void attachBufferToCamera( flightgear::CameraInfo* info, osg::Camera* camera, osg::Camera::BufferComponent c, const std::string& ck, const std::string& bk )
+void attachBufferToCamera( CameraInfo* info, osg::Camera* camera, osg::Camera::BufferComponent c, const std::string& ck, const std::string& bk )
{
camera->attach( c, info->getBuffer(bk) );
info->getRenderStageInfo(ck).buffers.insert( std::make_pair( c, bk ) );
}
-osg::Camera* FGRenderer::buildDeferredGeometryCamera( flightgear::CameraInfo* info, osg::GraphicsContext* gc )
+void buildAttachments(CameraInfo* info, osg::Camera* camera, const std::string& name, const std::vector<ref_ptr<FGRenderingPipeline::Attachment> > &attachments) {
+ BOOST_FOREACH(ref_ptr<FGRenderingPipeline::Attachment> attachment, attachments) {
+ if (attachment->valid())
+ attachBufferToCamera( info, camera, attachment->component, name, attachment->buffer );
+ }
+}
+
+osg::Camera* FGRenderer::buildDeferredGeometryCamera( CameraInfo* info, osg::GraphicsContext* gc, const std::string& name, const std::vector<ref_ptr<FGRenderingPipeline::Attachment> > &attachments )
{
osg::Camera* camera = new osg::Camera;
- info->addCamera(flightgear::GEOMETRY_CAMERA, camera );
+ info->addCamera(name, camera );
camera->setCullMask( ~simgear::MODELLIGHT_BIT );
camera->setName( "GeometryC" );
+ camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
camera->setGraphicsContext( gc );
- camera->setCullCallback( new FGDeferredRenderingCameraCullCallback( flightgear::GEOMETRY_CAMERA, info ) );
+ camera->setCullCallback( new FGDeferredRenderingCameraCullCallback( name, info ) );
camera->setClearMask( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
camera->setClearColor( osg::Vec4( 0., 0., 0., 0. ) );
camera->setClearDepth( 1.0 );
+ camera->setColorMask(true, true, true, true);
camera->setRenderTargetImplementation( osg::Camera::FRAME_BUFFER_OBJECT );
+ camera->setRenderOrder(osg::Camera::NESTED_RENDER, 0);
camera->setViewport( new osg::Viewport );
- attachBufferToCamera( info, camera, osg::Camera::COLOR_BUFFER0, flightgear::GEOMETRY_CAMERA, "normal" );
- attachBufferToCamera( info, camera, osg::Camera::COLOR_BUFFER1, flightgear::GEOMETRY_CAMERA, "diffuse" );
- attachBufferToCamera( info, camera, osg::Camera::COLOR_BUFFER2, flightgear::GEOMETRY_CAMERA, "spec-emis" );
- if (_useColorForDepth) {
- attachBufferToCamera( info, camera, osg::Camera::DEPTH_BUFFER, flightgear::GEOMETRY_CAMERA, "real-depth" );
- attachBufferToCamera( info, camera, osg::Camera::COLOR_BUFFER3, flightgear::GEOMETRY_CAMERA, "depth" );
- } else {
- attachBufferToCamera( info, camera, osg::Camera::DEPTH_BUFFER, flightgear::GEOMETRY_CAMERA, "depth" );
- }
+ buildAttachments(info, camera, name, attachments);
camera->setDrawBuffer(GL_FRONT);
camera->setReadBuffer(GL_FRONT);
osg::StateSet* ss = camera->getOrCreateStateSet();
ss->addUniform( _depthInColor );
- camera->addChild( mDeferredRealRoot.get() );
+ camera->addChild( _deferredRealRoot.get() );
return camera;
}
oss << "CascadeCamera" << (no + 1);
cascadeCam->setName( oss.str() );
cascadeCam->setClearMask(0);
- cascadeCam->setCullMask(~( simgear::MODELLIGHT_BIT /* | simgear::NO_SHADOW_BIT */ ) );
- cascadeCam->setCullingMode( cascadeCam->getCullingMode() & ~osg::CullSettings::SMALL_FEATURE_CULLING );
+ cascadeCam->setCullMask( simgear::CASTSHADOW_BIT );
+ cascadeCam->setCullingMode( cascadeCam->getCullingMode() | osg::CullSettings::SMALL_FEATURE_CULLING );
cascadeCam->setAllowEventFocus(false);
cascadeCam->setReferenceFrame(osg::Transform::ABSOLUTE_RF_INHERIT_VIEWPOINT);
cascadeCam->setRenderOrder(osg::Camera::NESTED_RENDER);
return cascadeCam;
}
-osg::Camera* FGRenderer::buildDeferredShadowCamera( flightgear::CameraInfo* info, osg::GraphicsContext* gc )
+osg::Camera* FGRenderer::buildDeferredShadowCamera( CameraInfo* info, osg::GraphicsContext* gc, const std::string& name, const std::vector<ref_ptr<FGRenderingPipeline::Attachment> > &attachments )
{
osg::Camera* mainShadowCamera = new osg::Camera;
- info->addCamera(flightgear::SHADOW_CAMERA, mainShadowCamera, 0.0f );
+ info->addCamera(name, mainShadowCamera, 0.0f );
mainShadowCamera->setName( "ShadowC" );
mainShadowCamera->setClearMask( GL_DEPTH_BUFFER_BIT );
mainShadowCamera->setAllowEventFocus(false);
mainShadowCamera->setGraphicsContext(gc);
mainShadowCamera->setRenderTargetImplementation( osg::Camera::FRAME_BUFFER_OBJECT );
- attachBufferToCamera( info, mainShadowCamera, osg::Camera::DEPTH_BUFFER, flightgear::SHADOW_CAMERA, "shadow" );
+ buildAttachments(info, mainShadowCamera, name, attachments);
mainShadowCamera->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR);
mainShadowCamera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
mainShadowCamera->setProjectionMatrix(osg::Matrix::identity());
mainShadowCamera->setViewport( 0, 0, _shadowMapSize, _shadowMapSize );
mainShadowCamera->setDrawBuffer(GL_FRONT);
mainShadowCamera->setReadBuffer(GL_FRONT);
+ mainShadowCamera->setRenderOrder(Camera::NESTED_RENDER, 1);
osg::Switch* shadowSwitch = new osg::Switch;
mainShadowCamera->addChild( shadowSwitch );
for (int i = 0; i < 4; ++i ) {
osg::Camera* cascadeCam = createShadowCascadeCamera( i, _shadowMapSize/2 );
- cascadeCam->addChild( mDeferredRealRoot.get() );
+ cascadeCam->addChild( _deferredRealRoot.get() );
shadowSwitch->addChild( cascadeCam );
- info->shadowTexGen[i] = new osg::TexGen;
}
if (fgGetBool("/sim/rendering/shadows/enabled", true))
shadowSwitch->setAllChildrenOn();
return val;
}
-void FGRenderer::updateShadowCamera(const flightgear::CameraInfo* info, const osg::Vec3d& position)
+void FGRenderer::updateShadowCamera(const CameraInfo* info, const osg::Vec3d& position)
{
ref_ptr<Camera> mainShadowCamera = info->getCamera( SHADOW_CAMERA );
if (mainShadowCamera.valid()) {
_shadowNumber->set( (int)_numCascades );
}
-osg::Camera* FGRenderer::buildDeferredLightingCamera( flightgear::CameraInfo* info, osg::GraphicsContext* gc )
+class DebugPassListener : public SGPropertyChangeListener {
+public:
+ DebugPassListener(osg::Switch* sw, int i) : _switch(sw), _index(i) {}
+ virtual void valueChanged(SGPropertyNode* node) {
+ _switch->setValue(_index, node->getBoolValue());
+ }
+
+private:
+ osg::ref_ptr<osg::Switch> _switch;
+ int _index;
+};
+
+osg::Camera*
+FGRenderer::buildDeferredLightingCamera( flightgear::CameraInfo* info, osg::GraphicsContext* gc, const FGRenderingPipeline::Stage* stage )
{
osg::Camera* camera = new osg::Camera;
- info->addCamera(flightgear::LIGHTING_CAMERA, camera );
+ info->addCamera(stage->name, camera );
- camera->setCullCallback( new FGDeferredRenderingCameraCullCallback( flightgear::LIGHTING_CAMERA, info ) );
+ camera->setCullCallback( new FGDeferredRenderingCameraCullCallback( stage->name, info ) );
camera->setAllowEventFocus(false);
camera->setGraphicsContext(gc);
camera->setViewport(new Viewport);
- camera->setName("LightingC");
+ camera->setName(stage->name+"C");
camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
- camera->setRenderOrder(osg::Camera::POST_RENDER, 50);
+ camera->setRenderOrder(osg::Camera::NESTED_RENDER, stage->orderNum);
camera->setRenderTargetImplementation( osg::Camera::FRAME_BUFFER_OBJECT );
camera->setViewport( new osg::Viewport );
- attachBufferToCamera( info, camera, osg::Camera::COLOR_BUFFER, flightgear::LIGHTING_CAMERA, "lighting" );
- if (_useColorForDepth) {
- attachBufferToCamera( info, camera, osg::Camera::DEPTH_BUFFER, flightgear::GEOMETRY_CAMERA, "real-depth" );
- } else {
- attachBufferToCamera( info, camera, osg::Camera::DEPTH_BUFFER, flightgear::GEOMETRY_CAMERA, "depth" );
- }
+ buildAttachments(info, camera, stage->name, stage->attachments);
camera->setDrawBuffer(GL_FRONT);
camera->setReadBuffer(GL_FRONT);
- camera->setClearColor( osg::Vec4( 0., 0., 0., 1. ) );
camera->setClearMask( GL_COLOR_BUFFER_BIT );
osg::StateSet* ss = camera->getOrCreateStateSet();
ss->setAttribute( new osg::Depth(osg::Depth::LESS, 0.0, 1.0, false) );
ss->addUniform( _depthInColor );
- osg::Group* lightingGroup = new osg::Group;
-
- osg::Camera* quadCam1 = new osg::Camera;
- quadCam1->setName( "QuadCamera1" );
- quadCam1->setClearMask(0);
- quadCam1->setAllowEventFocus(false);
- quadCam1->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
- quadCam1->setRenderOrder(osg::Camera::NESTED_RENDER);
- quadCam1->setViewMatrix(osg::Matrix::identity());
- quadCam1->setProjectionMatrixAsOrtho2D(-1,1,-1,1);
- quadCam1->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
- ss = quadCam1->getOrCreateStateSet();
- ss->addUniform( _ambientFactor );
+ osg::Switch* lightingGroup = new osg::Switch;
+
+ BOOST_FOREACH( osg::ref_ptr<FGRenderingPipeline::Pass> pass, stage->passes ) {
+ ref_ptr<Node> node = buildPass(info, pass);
+ if (node.valid()) {
+ lightingGroup->addChild(node);
+ if (!pass->debugProperty.empty()) {
+ lightingGroup->setValue(lightingGroup->getNumChildren()-1, fgGetBool(pass->debugProperty));
+ fgAddChangeListener(new DebugPassListener(lightingGroup, lightingGroup->getNumChildren()-1), pass->debugProperty);
+ }
+ }
+ }
+
+ camera->addChild( lightingGroup );
+
+ return camera;
+}
+
+CameraInfo*
+FGRenderer::buildDeferredPipeline(CameraGroup* cgroup, unsigned flags, osg::Camera* camera,
+ const osg::Matrix& view,
+ const osg::Matrix& projection,
+ osg::GraphicsContext* gc)
+{
+ return buildCameraFromRenderingPipeline(_pipeline, cgroup, flags, camera, view, projection, gc);
+}
+
+osg::Camera*
+FGRenderer::buildDeferredFullscreenCamera( flightgear::CameraInfo* info, const FGRenderingPipeline::Pass* pass )
+{
+ osg::Camera* camera = new osg::Camera;
+
+ camera->setClearMask( 0 );
+ camera->setAllowEventFocus(false);
+ camera->setName(pass->name+"C");
+ camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
+ camera->setRenderOrder(osg::Camera::NESTED_RENDER, pass->orderNum);
+ camera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
+ camera->setViewMatrix(osg::Matrix::identity());
+ camera->setProjectionMatrixAsOrtho2D(-1,1,-1,1);
+
+ osg::StateSet* ss = camera->getOrCreateStateSet();
+ ss->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
ss->addUniform( info->projInverse );
ss->addUniform( info->viewInverse );
ss->addUniform( info->view );
+ ss->addUniform( info->bufferSize );
+ ss->addUniform( info->worldPosCart );
+ ss->addUniform( info->worldPosGeod );
+ ss->addUniform( info->shadowMatrix[0] );
+ ss->addUniform( info->shadowMatrix[1] );
+ ss->addUniform( info->shadowMatrix[2] );
+ ss->addUniform( info->shadowMatrix[3] );
+ ss->addUniform( _ambientFactor );
ss->addUniform( _sunDiffuse );
ss->addUniform( _sunSpecular );
ss->addUniform( _sunDirection );
ss->addUniform( _planes );
ss->addUniform( _shadowNumber );
ss->addUniform( _shadowDistances );
+ ss->addUniform( _fogColor );
+ ss->addUniform( _fogDensity );
osg::Geometry* g = osg::createTexturedQuadGeometry( osg::Vec3(-1.,-1.,0.), osg::Vec3(2.,0.,0.), osg::Vec3(0.,2.,0.) );
g->setUseDisplayList(false);
simgear::EffectGeode* eg = new simgear::EffectGeode;
- simgear::Effect* effect = simgear::makeEffect("Effects/ambient", true);
- if (!effect) {
- SG_LOG(SG_VIEW, SG_ALERT, "Effects/ambient not found");
- return 0;
+ osg::ref_ptr<SGReaderWriterOptions> opt;
+ opt = SGReaderWriterOptions::fromPath(globals->get_fg_root());
+ opt->setPropertyNode(globals->get_props());
+ simgear::Effect* effect = simgear::makeEffect(pass->effect, true, opt.get());
+ if (effect) {
+ eg->setEffect( effect );
}
- eg->setEffect( effect );
- g->setName( "AmbientQuad" );
- eg->setName("AmbientQuad");
- eg->setCullingActive(false);
- eg->addDrawable(g);
- quadCam1->addChild( eg );
- g = osg::createTexturedQuadGeometry( osg::Vec3(-1.,-1.,0.), osg::Vec3(2.,0.,0.), osg::Vec3(0.,2.,0.) );
- g->setUseDisplayList(false);
- g->setName( "SunlightQuad" );
- eg = new simgear::EffectGeode;
- effect = simgear::makeEffect("Effects/sunlight", true);
- if (!effect) {
- SG_LOG(SG_VIEW, SG_ALERT, "Effects/sunlight not found");
- return 0;
- }
- eg->setEffect( effect );
- eg->setName("SunlightQuad");
+ eg->setName(pass->name+"Quad");
eg->setCullingActive(false);
eg->addDrawable(g);
- quadCam1->addChild( eg );
+ camera->addChild(eg);
- osg::Camera* lightCam = new osg::Camera;
- ss = lightCam->getOrCreateStateSet();
- ss->addUniform( _planes );
- ss->addUniform( info->bufferSize );
- lightCam->setName( "LightCamera" );
- lightCam->setClearMask(0);
- lightCam->setAllowEventFocus(false);
- lightCam->setReferenceFrame(osg::Transform::RELATIVE_RF);
- lightCam->setRenderOrder(osg::Camera::NESTED_RENDER,1);
- lightCam->setViewMatrix(osg::Matrix::identity());
- lightCam->setProjectionMatrix(osg::Matrix::identity());
- lightCam->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
- lightCam->setCullMask( simgear::MODELLIGHT_BIT );
- lightCam->setInheritanceMask( osg::CullSettings::ALL_VARIABLES & ~osg::CullSettings::CULL_MASK );
- lightCam->addChild( mDeferredRealRoot.get() );
-
-
- osg::Camera* quadCam2 = new osg::Camera;
- quadCam2->setName( "QuadCamera1" );
- quadCam2->setClearMask(0);
- quadCam2->setAllowEventFocus(false);
- quadCam2->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
- quadCam2->setRenderOrder(osg::Camera::NESTED_RENDER,2);
- quadCam2->setViewMatrix(osg::Matrix::identity());
- quadCam2->setProjectionMatrixAsOrtho2D(-1,1,-1,1);
- quadCam2->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
- ss = quadCam2->getOrCreateStateSet();
- ss->addUniform( _ambientFactor );
- ss->addUniform( info->projInverse );
- ss->addUniform( info->viewInverse );
- ss->addUniform( info->view );
- ss->addUniform( _sunDiffuse );
- ss->addUniform( _sunSpecular );
- ss->addUniform( _sunDirection );
- ss->addUniform( _fogColor );
- ss->addUniform( _fogDensity );
- ss->addUniform( _planes );
+ return camera;
+}
- g = osg::createTexturedQuadGeometry( osg::Vec3(-1.,-1.,0.), osg::Vec3(2.,0.,0.), osg::Vec3(0.,2.,0.) );
- g->setUseDisplayList(false);
- g->setName( "FogQuad" );
- eg = new simgear::EffectGeode;
- effect = simgear::makeEffect("Effects/fog", true);
- if (!effect) {
- SG_LOG(SG_VIEW, SG_ALERT, "Effects/fog not found");
- return 0;
- }
- eg->setEffect( effect );
- eg->setName("FogQuad");
- eg->setCullingActive(false);
- eg->addDrawable(g);
- quadCam2->addChild( eg );
+osg::Camera*
+FGRenderer::buildDeferredFullscreenCamera( flightgear::CameraInfo* info, osg::GraphicsContext* gc, const FGRenderingPipeline::Stage* stage )
+{
+ osg::Camera* camera = buildDeferredFullscreenCamera(info, static_cast<const FGRenderingPipeline::Pass*>(stage));
+ info->addCamera(stage->name, camera, stage->scaleFactor, true);
- lightingGroup->addChild( _sky->getPreRoot() );
- lightingGroup->addChild( _sky->getCloudRoot() );
- lightingGroup->addChild( quadCam1 );
- lightingGroup->addChild( lightCam );
- lightingGroup->addChild( quadCam2 );
+ camera->setCullCallback( new FGDeferredRenderingCameraCullCallback(stage->name, info, stage->needsDuDv) );
+ camera->setGraphicsContext(gc);
+ camera->setViewport(new Viewport);
+ camera->setRenderTargetImplementation( osg::Camera::FRAME_BUFFER_OBJECT );
+ buildAttachments(info, camera, stage->name, stage->attachments);
+ camera->setDrawBuffer(GL_FRONT);
+ camera->setReadBuffer(GL_FRONT);
+ camera->setClearColor( osg::Vec4( 1., 1., 1., 1. ) );
+ camera->setClearMask( GL_COLOR_BUFFER_BIT );
+ camera->setViewMatrix(osg::Matrix::identity());
+ camera->setProjectionMatrixAsOrtho2D(-1,1,-1,1);
- camera->addChild( lightingGroup );
+ osg::StateSet* ss = camera->getOrCreateStateSet();
+ if (stage->needsDuDv) {
+ ss->addUniform( info->du );
+ ss->addUniform( info->dv );
+ }
return camera;
}
-flightgear::CameraInfo*
-FGRenderer::buildDeferredPipeline(flightgear::CameraGroup* cgroup, unsigned flags, osg::Camera* camera,
- const osg::Matrix& view,
- const osg::Matrix& projection,
- osg::GraphicsContext* gc)
+void
+FGRenderer::buildDeferredDisplayCamera( osg::Camera* camera, flightgear::CameraInfo* info, const FGRenderingPipeline::Stage* stage, osg::GraphicsContext* gc )
{
- CameraInfo* info = new CameraInfo(flags);
- buildDeferredBuffers(info, _shadowMapSize, _useColorForDepth);
-
- osg::Camera* geometryCamera = buildDeferredGeometryCamera( info, gc );
- cgroup->getViewer()->addSlave(geometryCamera, false);
- installCullVisitor(geometryCamera);
- int slaveIndex = cgroup->getViewer()->getNumSlaves() - 1;
- info->getRenderStageInfo(GEOMETRY_CAMERA).slaveIndex = slaveIndex;
-
- Camera* shadowCamera = buildDeferredShadowCamera( info, gc );
- cgroup->getViewer()->addSlave(shadowCamera, false);
- installCullVisitor(shadowCamera);
- slaveIndex = cgroup->getViewer()->getNumSlaves() - 1;
- info->getRenderStageInfo(SHADOW_CAMERA).slaveIndex = slaveIndex;
-
- osg::Camera* lightingCamera = buildDeferredLightingCamera( info, gc );
- cgroup->getViewer()->addSlave(lightingCamera, false);
- installCullVisitor(lightingCamera);
- slaveIndex = cgroup->getViewer()->getNumSlaves() - 1;
- info->getRenderStageInfo(LIGHTING_CAMERA).slaveIndex = slaveIndex;
-
camera->setName( "DisplayC" );
- camera->setCullCallback( new FGDeferredRenderingCameraCullCallback( flightgear::DISPLAY_CAMERA, info ) );
+ camera->setCullCallback( new FGDeferredRenderingCameraCullCallback( stage->name, info ) );
camera->setReferenceFrame(Transform::ABSOLUTE_RF);
camera->setAllowEventFocus(false);
osg::Geometry* g = osg::createTexturedQuadGeometry( osg::Vec3(-1.,-1.,0.), osg::Vec3(2.,0.,0.), osg::Vec3(0.,2.,0.) );
g->setUseDisplayList(false); //DEBUG
simgear::EffectGeode* eg = new simgear::EffectGeode;
- simgear::Effect* effect = simgear::makeEffect("Effects/display", true);
+ osg::ref_ptr<SGReaderWriterOptions> opt;
+ opt = SGReaderWriterOptions::fromPath(globals->get_fg_root());
+ opt->setPropertyNode(globals->get_props());
+ simgear::Effect* effect = simgear::makeEffect(stage->effect, true, opt.get());
if (!effect) {
- SG_LOG(SG_VIEW, SG_ALERT, "Effects/display not found");
- return 0;
+ SG_LOG(SG_VIEW, SG_ALERT, stage->effect + " not found");
+ return;
}
eg->setEffect(effect);
eg->setCullingActive(false);
osg::StateSet* ss = camera->getOrCreateStateSet();
ss->addUniform( _depthInColor );
+ ss->addUniform( info->projInverse );
+ ss->addUniform( info->viewInverse );
+ ss->addUniform( info->view );
+ ss->addUniform( info->bufferSize );
+ ss->addUniform( info->worldPosCart );
+ ss->addUniform( info->worldPosGeod );
+ ss->addUniform( info->shadowMatrix[0] );
+ ss->addUniform( info->shadowMatrix[1] );
+ ss->addUniform( info->shadowMatrix[2] );
+ ss->addUniform( info->shadowMatrix[3] );
+ ss->addUniform( _ambientFactor );
+ ss->addUniform( _sunDiffuse );
+ ss->addUniform( _sunSpecular );
+ ss->addUniform( _sunDirection );
+ ss->addUniform( _planes );
+ ss->addUniform( _shadowNumber );
+ ss->addUniform( _shadowDistances );
+ ss->addUniform( _fogColor );
+ ss->addUniform( _fogDensity );
+}
- cgroup->getViewer()->addSlave(camera, false);
+void
+FGRenderer::buildStage(CameraInfo* info,
+ FGRenderingPipeline::Stage* stage,
+ CameraGroup* cgroup,
+ osg::Camera* mainCamera,
+ const osg::Matrix& view, const osg::Matrix& projection, osg::GraphicsContext* gc)
+{
+ if (!stage->valid())
+ return;
+
+ ref_ptr<Camera> camera;
+ bool needOffsets = false;
+ if (stage->type == "geometry") {
+ camera = buildDeferredGeometryCamera(info, gc, stage->name, stage->attachments);
+ needOffsets = true;
+ } else if (stage->type == "lighting") {
+ camera = buildDeferredLightingCamera(info, gc, stage);
+ needOffsets = true;
+ } else if (stage->type == "shadow")
+ camera = buildDeferredShadowCamera(info, gc, stage->name, stage->attachments);
+ else if (stage->type == "fullscreen")
+ camera = buildDeferredFullscreenCamera(info, gc, stage);
+ else if (stage->type == "display") {
+ camera = mainCamera;
+ buildDeferredDisplayCamera(camera, info, stage, gc);
+ } else
+ throw sg_exception("Stage type is not supported");
+
+ if (needOffsets)
+ cgroup->getViewer()->addSlave(camera, projection, view, false);
+ else
+ cgroup->getViewer()->addSlave(camera, false);
installCullVisitor(camera);
- slaveIndex = cgroup->getViewer()->getNumSlaves() - 1;
- info->addCamera( DISPLAY_CAMERA, camera, slaveIndex, true );
- camera->setRenderOrder(Camera::POST_RENDER, 99+slaveIndex); //FIXME
- cgroup->addCamera(info);
- return info;
+ int slaveIndex = cgroup->getViewer()->getNumSlaves() - 1;
+ if (stage->type == "display")
+ info->addCamera( stage->type, camera, slaveIndex, true );
+ info->getRenderStageInfo(stage->name).slaveIndex = slaveIndex;
}
+osg::Node*
+FGRenderer::buildLightingSkyCloudsPass(FGRenderingPipeline::Pass* pass)
+{
+ Group* group = new Group;
+ group->setName("skyCloudsGroup");
+ group->setNodeMask(simgear::BACKGROUND_BIT);
+
+ StateSet* ss = group->getOrCreateStateSet();
+ ss->setAttributeAndModes( new osg::ColorMask( true, true, true, false ), osg::StateAttribute::ON );
+ group->addChild( _sky->getPreRoot() );
+ group->addChild( _sky->getCloudRoot() );
+ return group;
+}
-void
-FGRenderer::setupView( void )
+osg::Node*
+FGRenderer::buildLightingLightsPass(CameraInfo* info, FGRenderingPipeline::Pass* pass)
{
- osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
- osg::initNotifyLevel();
+ osg::Camera* lightCam = new osg::Camera;
+ StateSet* ss = lightCam->getOrCreateStateSet();
+ ss->addUniform( _planes );
+ ss->addUniform( info->bufferSize );
+ ss->addUniform( _fogColor );
+ ss->addUniform( _fogDensity );
+ lightCam->setName( "LightCamera" );
+ lightCam->setClearMask(0);
+ lightCam->setAllowEventFocus(false);
+ lightCam->setReferenceFrame(osg::Transform::RELATIVE_RF);
+ lightCam->setRenderOrder(osg::Camera::NESTED_RENDER,pass->orderNum);
+ lightCam->setViewMatrix(osg::Matrix::identity());
+ lightCam->setProjectionMatrix(osg::Matrix::identity());
+ lightCam->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
+ lightCam->setCullMask( simgear::MODELLIGHT_BIT | simgear::PANEL2D_BIT | simgear::PERMANENTLIGHT_BIT);
+ lightCam->setInheritanceMask( osg::CullSettings::ALL_VARIABLES & ~osg::CullSettings::CULL_MASK );
+ lightCam->addChild( _deferredRealRoot.get() );
- // The number of polygon-offset "units" to place between layers. In
- // principle, one is supposed to be enough. In practice, I find that
- // my hardware/driver requires many more.
- osg::PolygonOffset::setUnitsMultiplier(1);
- osg::PolygonOffset::setFactorMultiplier(1);
+ return lightCam;
+}
- // Go full screen if requested ...
- if ( fgGetBool("/sim/startup/fullscreen") )
- fgOSFullScreen();
+osg::Node*
+FGRenderer::buildPass(CameraInfo* info, FGRenderingPipeline::Pass* pass)
+{
+ if (!pass->valid())
+ return 0;
-// build the sky
- // The sun and moon diameters are scaled down numbers of the
- // actual diameters. This was needed to fit both the sun and the
- // moon within the distance to the far clip plane.
- // Moon diameter: 3,476 kilometers
- // Sun diameter: 1,390,000 kilometers
- _sky->build( 80000.0, 80000.0,
- 463.3, 361.8,
- *globals->get_ephem(),
- fgGetNode("/environment", true));
-
- viewer->getCamera()
- ->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
+ ref_ptr<Node> node;
+ if (pass->type == "sky-clouds")
+ node = buildLightingSkyCloudsPass(pass);
+ else if (pass->type == "fullscreen")
+ node = buildDeferredFullscreenCamera(info, pass);
+ else if (pass->type == "lights")
+ node = buildLightingLightsPass(info, pass);
+ else
+ throw sg_exception("Pass type is not supported");
+
+ return node.release();
+}
+
+void
+FGRenderer::buildBuffers(FGRenderingPipeline* rpipe, CameraInfo* info)
+{
+ for (size_t i = 0; i < rpipe->buffers.size(); ++i) {
+ osg::ref_ptr<FGRenderingPipeline::Buffer> buffer = rpipe->buffers[i];
+ if (buffer->valid()) {
+ bool fullscreen = buffer->width == -1 && buffer->height == -1;
+ info->addBuffer(buffer->name, buildDeferredBuffer( buffer->internalFormat,
+ buffer->sourceFormat,
+ buffer->sourceType,
+ buffer->wrapMode,
+ buffer->shadowComparison),
+ fullscreen ? buffer->scaleFactor : 0.0f);
+ if (!fullscreen) {
+ info->getBuffer(buffer->name)->setTextureSize(buffer->width, buffer->height);
+ }
+ }
+ }
+}
+
+CameraInfo* FGRenderer::buildCameraFromRenderingPipeline(FGRenderingPipeline* rpipe, CameraGroup* cgroup, unsigned flags, osg::Camera* camera,
+ const osg::Matrix& view, const osg::Matrix& projection, osg::GraphicsContext* gc)
+{
+ CameraInfo* info = new CameraInfo(flags);
+ buildBuffers(rpipe, info);
- osg::StateSet* stateSet = mRoot->getOrCreateStateSet();
+ for (size_t i = 0; i < rpipe->stages.size(); ++i) {
+ osg::ref_ptr<FGRenderingPipeline::Stage> stage = rpipe->stages[i];
+ buildStage(info, stage, cgroup, camera, view, projection, gc);
+ }
+
+ cgroup->addCamera(info);
+
+ return info;
+}
+void FGRenderer::setupRoot()
+{
+ osg::StateSet* stateSet = _root->getOrCreateStateSet();
+
stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
stateSet->setAttribute(new osg::Depth(osg::Depth::LESS));
stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
-
- stateSet->setAttribute(new osg::AlphaFunc(osg::AlphaFunc::GREATER, 0.01));
- stateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::OFF);
+
stateSet->setAttribute(new osg::BlendFunc);
stateSet->setMode(GL_BLEND, osg::StateAttribute::OFF);
-
+
stateSet->setMode(GL_FOG, osg::StateAttribute::OFF);
// this will be set below
stateSet->setMode(GL_NORMALIZE, osg::StateAttribute::OFF);
-
+
osg::Material* material = new osg::Material;
stateSet->setAttribute(material);
stateSet->setTextureAttribute(0, new osg::TexEnv);
stateSet->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::OFF);
-
+
osg::Hint* hint = new osg::Hint(GL_FOG_HINT, GL_DONT_CARE);
hint->setUpdateCallback(new FGHintUpdateCallback("/sim/rendering/fog"));
stateSet->setAttribute(hint);
hint = new osg::Hint(GL_PERSPECTIVE_CORRECTION_HINT, GL_DONT_CARE);
hint->setUpdateCallback(new FGHintUpdateCallback("/sim/rendering/perspective-correction"));
stateSet->setAttribute(hint);
+}
+
+void
+FGRenderer::setupView( void )
+{
+ osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
+ osg::initNotifyLevel();
- osg::Group* sceneGroup = new osg::Group;
- sceneGroup->addChild(globals->get_scenery()->get_scene_graph());
- sceneGroup->setNodeMask(~simgear::BACKGROUND_BIT);
-
- //sceneGroup->addChild(thesky->getCloudRoot());
-
- stateSet = sceneGroup->getOrCreateStateSet();
- stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON);
+ // The number of polygon-offset "units" to place between layers. In
+ // principle, one is supposed to be enough. In practice, I find that
+ // my hardware/driver requires many more.
+ osg::PolygonOffset::setUnitsMultiplier(1);
+ osg::PolygonOffset::setFactorMultiplier(1);
+ setupRoot();
+
+// build the sky
+ // The sun and moon diameters are scaled down numbers of the
+ // actual diameters. This was needed to fit both the sun and the
+ // moon within the distance to the far clip plane.
+ // Moon diameter: 3,476 kilometers
+ // Sun diameter: 1,390,000 kilometers
+ osg::ref_ptr<SGReaderWriterOptions> opt;
+ opt = SGReaderWriterOptions::fromPath(globals->get_fg_root());
+ opt->setPropertyNode(globals->get_props());
+ _sky->build( 80000.0, 80000.0,
+ 463.3, 361.8,
+ *globals->get_ephem(),
+ fgGetNode("/environment", true),
+ opt.get());
+
+ viewer->getCamera()
+ ->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
+
+
// need to update the light on every frame
// OSG LightSource objects are rather confusing. OSG only supports
// the 10 lights specified by OpenGL itself; if more than one
// has the corresponding OpenGL light enabled: a LightSource will
// affect geometry anywhere in the scene graph that has its light
// number enabled in a state set.
- LightSource* lightSource = new LightSource;
+ osg::ref_ptr<LightSource> lightSource = new LightSource;
+ lightSource->setName("FGLightSource");
lightSource->getLight()->setDataVariance(Object::DYNAMIC);
// relative because of CameraView being just a clever transform node
lightSource->setReferenceFrame(osg::LightSource::RELATIVE_RF);
lightSource->setLocalStateSetModes(osg::StateAttribute::ON);
lightSource->setUpdateCallback(new FGLightSourceUpdateCallback);
- mRealRoot->addChild(lightSource);
+ _viewerSceneRoot->addChild(lightSource);
+
// we need a white diffuse light for the phase of the moon
- osg::LightSource* sunLight = new osg::LightSource;
+ osg::ref_ptr<LightSource> sunLight = new osg::LightSource;
+ sunLight->setName("sunLightSource");
sunLight->getLight()->setDataVariance(Object::DYNAMIC);
sunLight->getLight()->setLightNum(1);
sunLight->setUpdateCallback(new FGLightSourceUpdateCallback(true));
// Hang a StateSet above the sky subgraph in order to turn off
// light 0
- Group* skyGroup = new Group;
+ Group* skyGroup = _sky->getPreRoot();
StateSet* skySS = skyGroup->getOrCreateStateSet();
skySS->setMode(GL_LIGHT0, StateAttribute::OFF);
- skyGroup->addChild(_sky->getPreRoot());
sunLight->addChild(skyGroup);
- mRoot->addChild(sceneGroup);
- if ( _classicalRenderer )
- mRoot->addChild(sunLight);
- // Clouds are added to the scene graph later
- stateSet = globals->get_scenery()->get_scene_graph()->getOrCreateStateSet();
- stateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::ON);
+ if ( _classicalRenderer ) {
+ _root->addChild(sunLight);
+ }
+
+ osg::Group* sceneGroup = globals->get_scenery()->get_scene_graph();
+ sceneGroup->setName("rendererScene");
+ sceneGroup->setNodeMask(~simgear::BACKGROUND_BIT);
+ _root->addChild(sceneGroup);
+
+ // setup state-set for main scenery (including models and aircraft)
+ osg::StateSet* stateSet = sceneGroup->getOrCreateStateSet();
stateSet->setMode(GL_LIGHTING, osg::StateAttribute::ON);
stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON);
geode->addDrawable(new SGHUDDrawable);
guiCamera->addChild(geode);
- panelSwitch = new osg::Switch;
- osg::StateSet* stateSet = panelSwitch->getOrCreateStateSet();
- stateSet->setRenderBinDetails(1000, "RenderBin");
- // speed optimization?
- stateSet->setMode(GL_CULL_FACE, osg::StateAttribute::OFF);
- stateSet->setAttribute(new osg::BlendFunc(osg::BlendFunc::SRC_ALPHA, osg::BlendFunc::ONE_MINUS_SRC_ALPHA));
- stateSet->setMode(GL_BLEND, osg::StateAttribute::ON);
- stateSet->setMode(GL_FOG, osg::StateAttribute::OFF);
- stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
-
-
- panelSwitch->setUpdateCallback(new FGPanelSwitchCallback);
- panelChanged();
-
- guiCamera->addChild(panelSwitch.get());
+ guiCamera->addChild(FGPanelNode::create2DPanelNode());
}
osg::Switch* sw = new osg::Switch;
+ sw->setName("scenerySwitch");
sw->setUpdateCallback(new FGScenerySwitchCallback);
- sw->addChild(mRoot.get());
- mRealRoot->addChild(sw);
+ sw->addChild(_root.get());
+ _viewerSceneRoot->addChild(sw);
// The clouds are attached directly to the scene graph root
// because, in theory, they don't want the same default state set
// as the rest of the scene. This may not be true in practice.
- if ( _classicalRenderer ) {
- mRealRoot->addChild(_sky->getCloudRoot());
- mRealRoot->addChild(FGCreateRedoutNode());
- }
+ if ( _classicalRenderer ) {
+ _viewerSceneRoot->addChild(_sky->getCloudRoot());
+ _viewerSceneRoot->addChild(FGCreateRedoutNode());
+ }
+
// Attach empty program to the scene root so that shader programs
// don't leak into state sets (effects) that shouldn't have one.
- stateSet = mRealRoot->getOrCreateStateSet();
+ stateSet = _viewerSceneRoot->getOrCreateStateSet();
stateSet->setAttributeAndModes(new osg::Program, osg::StateAttribute::ON);
- mDeferredRealRoot->addChild( mRealRoot.get() );
-}
-
-void FGRenderer::panelChanged()
-{
- if (!panelSwitch) {
- return;
- }
-
- osg::Node* n = FGPanelNode::createNode(globals->get_current_panel());
- if (panelSwitch->getNumChildren()) {
- panelSwitch->setChild(0, n);
- } else {
- panelSwitch->addChild(n);
+ if ( !_classicalRenderer ) {
+ _deferredRealRoot->addChild( _viewerSceneRoot.get() );
}
}
-
+
// Update all Visuals (redraws anything graphics related)
void
FGRenderer::update( ) {
- if (!(_scenery_loaded->getBoolValue() ||
- _scenery_override->getBoolValue()))
+ if (!_position_finalized || !_scenery_loaded->getBoolValue())
{
_splash_alpha->setDoubleValue(1.0);
return;
osg::Camera *camera = viewer->getCamera();
- bool skyblend = _skyblend->getBoolValue();
- if ( skyblend ) {
-
- if ( _textures->getBoolValue() ) {
- SGVec4f clearColor(l->adj_fog_color());
- camera->setClearColor(toOsg(clearColor));
- }
- } else {
- SGVec4f clearColor(l->sky_color());
- camera->setClearColor(toOsg(clearColor));
- }
-
- // update fog params if visibility has changed
- double visibility_meters = _visibility_m->getDoubleValue();
- _sky->set_visibility(visibility_meters);
-
- double altitude_m = _altitude_ft->getDoubleValue() * SG_FEET_TO_METER;
- _sky->modify_vis( altitude_m, 0.0 /* time factor, now unused */);
-
- // update the sky dome
- if ( skyblend ) {
-
- // The sun and moon distances are scaled down versions
- // of the actual distance to get both the moon and the sun
- // within the range of the far clip plane.
- // Moon distance: 384,467 kilometers
- // Sun distance: 150,000,000 kilometers
-
- double sun_horiz_eff, moon_horiz_eff;
- if (_horizon_effect->getBoolValue()) {
- sun_horiz_eff
- = 0.67 + pow(osg::clampAbove(0.5 + cos(l->get_sun_angle()),
- 0.0),
- 0.33) / 3.0;
- moon_horiz_eff
- = 0.67 + pow(osg::clampAbove(0.5 + cos(l->get_moon_angle()),
- 0.0),
- 0.33)/3.0;
- } else {
- sun_horiz_eff = moon_horiz_eff = 1.0;
- }
-
- SGSkyState sstate;
- sstate.pos = current__view->getViewPosition();
- sstate.pos_geod = current__view->getPosition();
- sstate.ori = current__view->getViewOrientation();
- sstate.spin = l->get_sun_rotation();
- sstate.gst = globals->get_time_params()->getGst();
- sstate.sun_dist = 50000.0 * sun_horiz_eff;
- sstate.moon_dist = 40000.0 * moon_horiz_eff;
- sstate.sun_angle = l->get_sun_angle();
-
- SGSkyColor scolor;
- scolor.sky_color = SGVec3f(l->sky_color().data());
- scolor.adj_sky_color = SGVec3f(l->adj_sky_color().data());
- scolor.fog_color = SGVec3f(l->adj_fog_color().data());
- scolor.cloud_color = SGVec3f(l->cloud_color().data());
- scolor.sun_angle = l->get_sun_angle();
- scolor.moon_angle = l->get_moon_angle();
-
- double delta_time_sec = _sim_delta_sec->getDoubleValue();
- _sky->reposition( sstate, *globals->get_ephem(), delta_time_sec );
- _sky->repaint( scolor, *globals->get_ephem() );
-
- //OSGFIXME
-// shadows->setupShadows(
-// current__view->getLongitude_deg(),
-// current__view->getLatitude_deg(),
-// globals->get_time_params()->getGst(),
-// globals->get_ephem()->getSunRightAscension(),
-// globals->get_ephem()->getSunDeclination(),
-// l->get_sun_angle());
-
- }
-
-// sgEnviro.setLight(l->adj_fog_color());
-// sgEnviro.startOfFrame(current__view->get_view_pos(),
-// current__view->get_world_up(),
-// current__view->getLongitude_deg(),
-// current__view->getLatitude_deg(),
-// current__view->getAltitudeASL_ft() * SG_FEET_TO_METER,
-// delta_time_sec);
-
- // OSGFIXME
-// sgEnviro.drawLightning();
-
-// double current_view_origin_airspeed_horiz_kt =
-// fgGetDouble("/velocities/airspeed-kt", 0.0)
-// * cos( fgGetDouble("/orientation/pitch-deg", 0.0)
-// * SGD_DEGREES_TO_RADIANS);
-
- // OSGFIXME
-// if( is_internal )
-// shadows->endOfFrame();
+ SGVec4f clearColor(l->adj_fog_color());
+ camera->setClearColor(toOsg(clearColor));
+ updateSky();
+
// need to call the update visitor once
- mFrameStamp->setCalendarTime(*globals->get_time_params()->getGmt());
- mUpdateVisitor->setViewData(current__view->getViewPosition(),
+ _frameStamp->setCalendarTime(*globals->get_time_params()->getGmt());
+ _updateVisitor->setViewData(current__view->getViewPosition(),
current__view->getViewOrientation());
SGVec3f direction(l->sun_vec()[0], l->sun_vec()[1], l->sun_vec()[2]);
- mUpdateVisitor->setLight(direction, l->scene_ambient(),
+ _updateVisitor->setLight(direction, l->scene_ambient(),
l->scene_diffuse(), l->scene_specular(),
l->adj_fog_color(),
l->get_sun_angle()*SGD_RADIANS_TO_DEGREES);
- mUpdateVisitor->setVisibility(actual_visibility);
- simgear::GroundLightManager::instance()->update(mUpdateVisitor.get());
+ _updateVisitor->setVisibility(actual_visibility);
+ simgear::GroundLightManager::instance()->update(_updateVisitor.get());
osg::Node::NodeMask cullMask = ~simgear::LIGHTS_BITS & ~simgear::PICK_BIT;
cullMask |= simgear::GroundLightManager::instance()
- ->getLightNodeMask(mUpdateVisitor.get());
+ ->getLightNodeMask(_updateVisitor.get());
if (_panel_hotspots->getBoolValue())
cullMask |= simgear::PICK_BIT;
CameraGroup::getDefault()->setCameraCullMasks(cullMask);
if ( !_classicalRenderer ) {
_fogColor->set( toOsg( l->adj_fog_color() ) );
- _fogDensity->set( float( mUpdateVisitor->getFogExp2Density() ) );
+ _fogDensity->set( float( _updateVisitor->getFogExp2Density() ) );
}
}
+void
+FGRenderer::updateSky()
+{
+ // update fog params if visibility has changed
+ double visibility_meters = _visibility_m->getDoubleValue();
+ _sky->set_visibility(visibility_meters);
+
+ double altitude_m = _altitude_ft->getDoubleValue() * SG_FEET_TO_METER;
+ _sky->modify_vis( altitude_m, 0.0 /* time factor, now unused */);
+
+ FGLight *l = static_cast<FGLight*>(globals->get_subsystem("lighting"));
+
+ // The sun and moon distances are scaled down versions
+ // of the actual distance to get both the moon and the sun
+ // within the range of the far clip plane.
+ // Moon distance: 384,467 kilometers
+ // Sun distance: 150,000,000 kilometers
+
+ double sun_horiz_eff, moon_horiz_eff;
+ if (_horizon_effect->getBoolValue()) {
+ sun_horiz_eff
+ = 0.67 + pow(osg::clampAbove(0.5 + cos(l->get_sun_angle()),
+ 0.0),
+ 0.33) / 3.0;
+ moon_horiz_eff
+ = 0.67 + pow(osg::clampAbove(0.5 + cos(l->get_moon_angle()),
+ 0.0),
+ 0.33)/3.0;
+ } else {
+ sun_horiz_eff = moon_horiz_eff = 1.0;
+ }
+
+ SGSkyState sstate;
+ sstate.pos = globals->get_current_view()->getViewPosition();
+ sstate.pos_geod = globals->get_current_view()->getPosition();
+ sstate.ori = globals->get_current_view()->getViewOrientation();
+ sstate.spin = l->get_sun_rotation();
+ sstate.gst = globals->get_time_params()->getGst();
+ sstate.sun_dist = 50000.0 * sun_horiz_eff;
+ sstate.moon_dist = 40000.0 * moon_horiz_eff;
+ sstate.sun_angle = l->get_sun_angle();
+
+ SGSkyColor scolor;
+ scolor.sky_color = SGVec3f(l->sky_color().data());
+ scolor.adj_sky_color = SGVec3f(l->adj_sky_color().data());
+ scolor.fog_color = SGVec3f(l->adj_fog_color().data());
+ scolor.cloud_color = SGVec3f(l->cloud_color().data());
+ scolor.sun_angle = l->get_sun_angle();
+ scolor.moon_angle = l->get_moon_angle();
+
+ double delta_time_sec = _sim_delta_sec->getDoubleValue();
+ _sky->reposition( sstate, *globals->get_ephem(), delta_time_sec );
+ _sky->repaint( scolor, *globals->get_ephem() );
+}
+
void
FGRenderer::resize( int width, int height )
{
}
}
+typedef osgUtil::LineSegmentIntersector::Intersection Intersection;
+SGVec2d uvFromIntersection(const Intersection& hit)
+{
+ // Taken from http://trac.openscenegraph.org/projects/osg/browser/OpenSceneGraph/trunk/examples/osgmovie/osgmovie.cpp
+
+ osg::Drawable* drawable = hit.drawable.get();
+ osg::Geometry* geometry = drawable ? drawable->asGeometry() : 0;
+ osg::Vec3Array* vertices =
+ geometry ? dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray()) : 0;
+
+ if( !vertices )
+ {
+ SG_LOG(SG_INPUT, SG_WARN, "Unable to get vertices for intersection.");
+ return SGVec2d(-9999,-9999);
+ }
+
+ // get the vertex indices.
+ const Intersection::IndexList& indices = hit.indexList;
+ const Intersection::RatioList& ratios = hit.ratioList;
+
+ if( indices.size() != 3 || ratios.size() != 3 )
+ {
+ SG_LOG( SG_INPUT,
+ SG_WARN,
+ "Intersection has insufficient indices to work with." );
+ return SGVec2d(-9999,-9999);
+ }
+
+ unsigned int i1 = indices[0];
+ unsigned int i2 = indices[1];
+ unsigned int i3 = indices[2];
+
+ float r1 = ratios[0];
+ float r2 = ratios[1];
+ float r3 = ratios[2];
+
+ osg::Array* texcoords =
+ (geometry->getNumTexCoordArrays() > 0) ? geometry->getTexCoordArray(0) : 0;
+ osg::Vec2Array* texcoords_Vec2Array =
+ dynamic_cast<osg::Vec2Array*>(texcoords);
+
+ if( !texcoords_Vec2Array )
+ {
+ SG_LOG(SG_INPUT, SG_WARN, "Unable to get texcoords for intersection.");
+ return SGVec2d(-9999,-9999);
+ }
+
+ // we have tex coord array so now we can compute the final tex coord at the
+ // point of intersection.
+ osg::Vec2 tc1 = (*texcoords_Vec2Array)[i1];
+ osg::Vec2 tc2 = (*texcoords_Vec2Array)[i2];
+ osg::Vec2 tc3 = (*texcoords_Vec2Array)[i3];
+
+ return toSG( osg::Vec2d(tc1 * r1 + tc2 * r2 + tc3 * r3) );
+}
+
bool
-FGRenderer::pick(std::vector<SGSceneryPick>& pickList,
- const osgGA::GUIEventAdapter* ea)
+FGRenderer::pick(std::vector<SGSceneryPick>& pickList, const osg::Vec2& windowPos)
{
// wipe out the return ...
pickList.clear();
typedef osgUtil::LineSegmentIntersector::Intersections Intersections;
Intersections intersections;
- if (!computeIntersections(CameraGroup::getDefault(), ea, intersections))
+ if (!computeIntersections(CameraGroup::getDefault(), windowPos, intersections))
return false;
for (Intersections::iterator hit = intersections.begin(),
e = 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 (!ud)
+ if (!ud || (ud->getNumPickCallbacks() == 0))
continue;
+
for (unsigned i = 0; i < ud->getNumPickCallbacks(); ++i) {
SGPickCallback* pickCallback = ud->getPickCallback(i);
if (!pickCallback)
SGSceneryPick sceneryPick;
sceneryPick.info.local = toSG(hit->getLocalIntersectPoint());
sceneryPick.info.wgs84 = toSG(hit->getWorldIntersectPoint());
+
+ if( pickCallback->needsUV() )
+ sceneryPick.info.uv = uvFromIntersection(*hit);
+
sceneryPick.callback = pickCallback;
pickList.push_back(sceneryPick);
- }
- }
+ } // of installed pick callbacks iteration
+ } // of reverse node path walk
}
+
return !pickList.empty();
}
void
FGRenderer::addCamera(osg::Camera* camera, bool useSceneData)
{
- mRealRoot->addChild(camera);
+ _viewerSceneRoot->addChild(camera);
}
void
FGRenderer::removeCamera(osg::Camera* camera)
{
- mRealRoot->removeChild(camera);
+ _viewerSceneRoot->removeChild(camera);
}
void
bool
fgDumpSceneGraphToFile(const char* filename)
{
- return osgDB::writeNodeFile(*mRealRoot.get(), filename);
+ osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
+ return osgDB::writeNodeFile(*viewer->getSceneData(), filename);
}
bool