#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>
};
bool FGScenerySwitchCallback::scenery_enabled = false;
-
-#ifdef FG_JPEG_SERVER
-static void updateRenderer()
-{
- globals->get_renderer()->update();
-}
-#endif
FGRenderer::FGRenderer() :
_sky(NULL),
_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
-
// it's not the real root, whatever that means
_root = new osg::Group;
_root->setName("fakeRoot");
_updateVisitor = new SGUpdateVisitor;
- _root = new osg::Group;
+
+ // 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;
}
// replace the viewer's scene completely
- getViewer()->setSceneData(new osg::Group);
-
+ if (getViewer()) {
+ getViewer()->setSceneData(new osg::Group);
+ }
-#ifdef FG_JPEG_SERVER
- jpgRenderFrame = NULL;
-#endif
delete _sky;
}
// critical parts of the scene graph in addition to the splash screen.
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();
viewer->setName("osgViewer");
- _viewerSceneRoot = dynamic_cast<osg::Group*>(viewer->getSceneData());
+ _viewerSceneRoot = new osg::Group;
_viewerSceneRoot->setName("viewerSceneRoot");
+ viewer->setSceneData(_viewerSceneRoot);
ref_ptr<Node> splashNode = fgCreateSplashNode();
if (_classicalRenderer) {
}
}
- _frameStamp = viewer->getFrameStamp();
+ _frameStamp = new osg::FrameStamp;
+ viewer->setFrameStamp(_frameStamp.get());
// Scene doesn't seem to pass the frame stamp to the update
// visitor automatically.
_updateVisitor->setFrameStamp(_frameStamp.get());
_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);
if (!_classicalRenderer) {
eventHandler->setChangeStatsCameraRenderOrder( true );
- _sky->set_minimum_sky_visibility( 0.0 ); // A black sky appears for below that
}
}
return info;
}
-void
-FGRenderer::setupView( void )
+void FGRenderer::setupRoot()
{
- osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
- osg::initNotifyLevel();
-
- // 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);
-
-// 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);
-
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->setName("rendererScene");
- 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
_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);
// Hang a StateSet above the sky subgraph in order to turn off
// light 0
- Group* skyGroup = new Group;
- skyGroup->setName("rendererSkyParent");
+ Group* skyGroup = _sky->getPreRoot();
StateSet* skySS = skyGroup->getOrCreateStateSet();
skySS->setMode(GL_LIGHT0, StateAttribute::OFF);
- skyGroup->addChild(_sky->getPreRoot());
sunLight->addChild(skyGroup);
- _root->addChild(sceneGroup);
- if ( _classicalRenderer )
+ if ( _classicalRenderer ) {
_root->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);
+ }
+
+ 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);
// 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 ) {
- _viewerSceneRoot->addChild(_sky->getCloudRoot());
- _viewerSceneRoot->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 = _viewerSceneRoot->getOrCreateStateSet();
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
_frameStamp->setCalendarTime(*globals->get_time_params()->getGmt());
_updateVisitor->setViewData(current__view->getViewPosition(),
}
}
+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 )
{