// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-//
-// $Id$
-
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
-#include <simgear/compiler.h>
-
#ifdef HAVE_WINDOWS_H
# include <windows.h>
#endif
+#include <simgear/compiler.h>
+
#include <osg/ref_ptr>
#include <osg/AlphaFunc>
#include <osg/BlendFunc>
#include <osg/Camera>
-#include <osg/CameraView>
#include <osg/CullFace>
#include <osg/Depth>
#include <osg/Fog>
#include <osg/Group>
+#include <osg/Hint>
#include <osg/Light>
#include <osg/LightModel>
#include <osg/LightSource>
+#include <osg/Material>
+#include <osg/Math>
#include <osg/NodeCallback>
#include <osg/Notify>
#include <osg/PolygonMode>
#include <osg/PolygonOffset>
-#include <osg/ShadeModel>
+#include <osg/Program>
+#include <osg/Version>
#include <osg/TexEnv>
-#include <osgUtil/SceneView>
-#include <osgUtil/UpdateVisitor>
-#include <osgUtil/IntersectVisitor>
+#include <osgUtil/LineSegmentIntersector>
#include <osg/io_utils>
#include <osgDB/WriteFile>
-#include <osgDB/ReadFile>
-#include <sstream>
#include <simgear/math/SGMath.hxx>
#include <simgear/screen/extensions.hxx>
#include <simgear/scene/material/matlib.hxx>
#include <simgear/scene/model/animation.hxx>
-#include <simgear/scene/model/model.hxx>
-#include <simgear/scene/model/modellib.hxx>
#include <simgear/scene/model/placement.hxx>
+#include <simgear/scene/sky/sky.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/structure/OSGUtils.hxx>
#include <simgear/props/props.hxx>
#include <simgear/timing/sg_time.hxx>
#include <simgear/ephemeris/ephemeris.hxx>
#include <simgear/environment/visual_enviro.hxx>
-#include <Scenery/tileentry.hxx>
#include <Time/light.hxx>
#include <Time/light.hxx>
#include <Aircraft/aircraft.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>
+#include <Environment/precipitation_mgr.hxx>
+#include <Include/general.hxx>
#include "splash.hxx"
#include "renderer.hxx"
#include "main.hxx"
+#include "CameraGroup.hxx"
+#include "FGEventHandler.hxx"
+#include <Main/viewer.hxx>
+
+using namespace osg;
+using namespace simgear;
+using namespace flightgear;
+
+class FGHintUpdateCallback : public osg::StateAttribute::Callback {
+public:
+ FGHintUpdateCallback(const char* configNode) :
+ mConfigNode(fgGetNode(configNode, true))
+ { }
+ virtual void operator()(osg::StateAttribute* stateAttribute,
+ osg::NodeVisitor*)
+ {
+ assert(dynamic_cast<osg::Hint*>(stateAttribute));
+ osg::Hint* hint = static_cast<osg::Hint*>(stateAttribute);
+
+ const char* value = mConfigNode->getStringValue();
+ if (!value)
+ hint->setMode(GL_DONT_CARE);
+ else if (0 == strcmp(value, "nicest"))
+ hint->setMode(GL_NICEST);
+ else if (0 == strcmp(value, "fastest"))
+ hint->setMode(GL_FASTEST);
+ else
+ hint->setMode(GL_DONT_CARE);
+ }
+private:
+ SGSharedPtr<SGPropertyNode> mConfigNode;
+};
+
class SGPuDrawable : public osg::Drawable {
public:
{
// Dynamic stuff, do not store geometry
setUseDisplayList(false);
+ setDataVariance(Object::DYNAMIC);
osg::StateSet* stateSet = getOrCreateStateSet();
stateSet->setRenderBinDetails(1001, "RenderBin");
{ drawImplementation(*renderInfo.getState()); }
void drawImplementation(osg::State& state) const
{
- state.pushStateSet(getStateSet());
- state.apply();
state.setActiveTextureUnit(0);
state.setClientActiveTextureUnit(0);
+
state.disableAllVertexArrays();
glPushAttrib(GL_ALL_ATTRIB_BITS);
glPushClientAttrib(~0u);
- if((fgGetBool("/sim/atc/enabled"))
- || (fgGetBool("/sim/ai-traffic/enabled")))
- globals->get_ATC_display()->update(delta_time_sec, state);
-
puDisplay();
glPopClientAttrib();
glPopAttrib();
-
- state.popStateSet();
- state.dirtyAllModes();
- state.dirtyAllAttributes();
- state.dirtyAllVertexArrays();
}
virtual osg::Object* cloneType() const { return new SGPuDrawable; }
{
// Dynamic stuff, do not store geometry
setUseDisplayList(false);
+ setDataVariance(Object::DYNAMIC);
osg::StateSet* stateSet = getOrCreateStateSet();
stateSet->setRenderBinDetails(1000, "RenderBin");
{ drawImplementation(*renderInfo.getState()); }
void drawImplementation(osg::State& state) const
{
- state.pushStateSet(getStateSet());
- state.apply();
state.setActiveTextureUnit(0);
state.setClientActiveTextureUnit(0);
state.disableAllVertexArrays();
glPopClientAttrib();
glPopAttrib();
- state.popStateSet();
- state.dirtyAllModes();
- state.dirtyAllAttributes();
- state.dirtyAllVertexArrays();
}
virtual osg::Object* cloneType() const { return new SGHUDAndPanelDrawable; }
class FGLightSourceUpdateCallback : public osg::NodeCallback {
public:
+
+ /**
+ * @param isSun true if the light is the actual sun i.e., for
+ * illuminating the moon.
+ */
+ FGLightSourceUpdateCallback(bool isSun = false) : _isSun(isSun) {}
+ FGLightSourceUpdateCallback(const FGLightSourceUpdateCallback& nc,
+ const CopyOp& op)
+ : NodeCallback(nc, op), _isSun(nc._isSun)
+ {}
+ META_Object(flightgear,FGLightSourceUpdateCallback);
+
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
{
assert(dynamic_cast<osg::LightSource*>(node));
osg::Light* light = lightSource->getLight();
FGLight *l = static_cast<FGLight*>(globals->get_subsystem("lighting"));
- light->setAmbient(l->scene_ambient().osg());
- light->setDiffuse(l->scene_diffuse().osg());
- light->setSpecular(l->scene_specular().osg());
- SGVec4f position(l->sun_vec()[0], l->sun_vec()[1], l->sun_vec()[2], 0);
- light->setPosition(position.osg());
- SGVec3f direction(l->sun_vec()[0], l->sun_vec()[1], l->sun_vec()[2]);
- light->setDirection(direction.osg());
- light->setSpotExponent(0);
- light->setSpotCutoff(180);
- light->setConstantAttenuation(1);
- light->setLinearAttenuation(0);
- light->setQuadraticAttenuation(0);
+ if (_isSun) {
+ light->setAmbient(Vec4(0.0f, 0.0f, 0.0f, 0.0f));
+ light->setDiffuse(Vec4(1.0f, 1.0f, 1.0f, 1.0f));
+ light->setSpecular(Vec4(0.0f, 0.0f, 0.0f, 0.0f));
+ } else {
+ light->setAmbient(toOsg(l->scene_ambient()));
+ light->setDiffuse(toOsg(l->scene_diffuse()));
+ light->setSpecular(toOsg(l->scene_specular()));
+ }
+ osg::Vec4f position(l->sun_vec()[0], l->sun_vec()[1], l->sun_vec()[2], 0);
+ light->setPosition(position);
traverse(node, nv);
}
+private:
+ const bool _isSun;
};
class FGWireFrameModeUpdateCallback : public osg::StateAttribute::Callback {
#if 0
FGLight *l = static_cast<FGLight*>(globals->get_subsystem("lighting"));
- lightModel->setAmbientIntensity(l->scene_ambient().osg());
+ lightModel->setAmbientIntensity(toOsg(l->scene_ambient());
#else
lightModel->setAmbientIntensity(osg::Vec4(0, 0, 0, 1));
#endif
SGSharedPtr<SGPropertyNode> mFogEnabled;
};
+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(toOsg(updateVisitor->getFogColor()));
+ fog->setDensity(updateVisitor->getFogExp2Density());
+ }
+};
+
// update callback for the switch node guarding that splash
class FGScenerySwitchCallback : public osg::NodeCallback {
public:
}
};
-// 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;
-
// Sky structures
SGSky *thesky;
-osg::ref_ptr<osgUtil::SceneView> sceneView = new osgUtil::SceneView; // This SceneView is used by class FGJpegHttpd ( jpg-httpd.cxx )
static osg::ref_ptr<osg::FrameStamp> mFrameStamp = new osg::FrameStamp;
static osg::ref_ptr<SGUpdateVisitor> mUpdateVisitor= new SGUpdateVisitor;
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
+ eventHandler = new FGEventHandler;
}
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::splashinit( void ) {
- // 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());
+ osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
+ mRealRoot = dynamic_cast<osg::Group*>(viewer->getSceneData());
+ mRealRoot->addChild(fgCreateSplashNode());
+ mFrameStamp = viewer->getFrameStamp();
+ // Scene doesn't seem to pass the frame stamp to the update
+ // visitor automatically.
+ mUpdateVisitor->setFrameStamp(mFrameStamp.get());
+ viewer->setUpdateVisitor(mUpdateVisitor.get());
}
void
-FGRenderer::init( void ) {
-
+FGRenderer::init( void )
+{
+ osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
osg::initNotifyLevel();
// The number of polygon-offset "units" to place between layers. In
if ( fgGetBool("/sim/startup/fullscreen") )
fgOSFullScreen();
- if ( (!strcmp(fgGetString("/sim/rendering/fog"), "disabled")) ||
- (!fgGetBool("/sim/rendering/shading"))) {
- // if fastest fog requested, or if flat shading force fastest
- glHint ( GL_FOG_HINT, GL_FASTEST );
- } else if ( !strcmp(fgGetString("/sim/rendering/fog"), "nicest") ) {
- glHint ( GL_FOG_HINT, GL_DONT_CARE );
- }
-
- glHint(GL_POLYGON_SMOOTH_HINT, GL_DONT_CARE);
- glHint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE);
- glHint(GL_POINT_SMOOTH_HINT, GL_DONT_CARE);
-
- mFog->setMode(osg::Fog::EXP2);
- mRunwayLightingFog->setMode(osg::Fog::EXP2);
- mTaxiLightingFog->setMode(osg::Fog::EXP2);
- mGroundLightingFog->setMode(osg::Fog::EXP2);
-
- sceneView->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
- sceneView->getCamera()->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
-
-
+ viewer->getCamera()
+ ->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
+
osg::StateSet* stateSet = mRoot->getOrCreateStateSet();
stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
stateSet->setTextureAttribute(0, new osg::TexEnv);
stateSet->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::OFF);
-
-// stateSet->setAttribute(new osg::CullFace(osg::CullFace::BACK));
-// stateSet->setMode(GL_CULL_FACE, osg::StateAttribute::ON);
-
- // this is the topmost scenegraph node for osg
- mBackGroundCamera->addChild(thesky->getPreRoot());
- mBackGroundCamera->setClearMask(0);
-
- GLbitfield inheritanceMask = osg::CullSettings::ALL_VARIABLES;
- inheritanceMask &= ~osg::CullSettings::COMPUTE_NEAR_FAR_MODE;
- inheritanceMask &= ~osg::CullSettings::NEAR_FAR_RATIO;
- inheritanceMask &= ~osg::CullSettings::CULLING_MODE;
- mBackGroundCamera->setInheritanceMask(inheritanceMask);
- mBackGroundCamera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
- mBackGroundCamera->setCullingMode(osg::CullSettings::NO_CULLING);
- mBackGroundCamera->setRenderOrder(osg::Camera::NESTED_RENDER);
-
- stateSet = mBackGroundCamera->getOrCreateStateSet();
- stateSet->setMode(GL_DEPTH_TEST, 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_POLYGON_SMOOTH_HINT, GL_DONT_CARE);
+ hint->setUpdateCallback(new FGHintUpdateCallback("/sim/rendering/polygon-smooth"));
+ stateSet->setAttribute(hint);
+ hint = new osg::Hint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE);
+ hint->setUpdateCallback(new FGHintUpdateCallback("/sim/rendering/line-smooth"));
+ stateSet->setAttribute(hint);
+ hint = new osg::Hint(GL_POINT_SMOOTH_HINT, GL_DONT_CARE);
+ hint->setUpdateCallback(new FGHintUpdateCallback("/sim/rendering/point-smooth"));
+ 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);
osg::Group* sceneGroup = new osg::Group;
sceneGroup->addChild(globals->get_scenery()->get_scene_graph());
- sceneGroup->addChild(thesky->getCloudRoot());
+ sceneGroup->setNodeMask(~simgear::BACKGROUND_BIT);
+
+ //sceneGroup->addChild(thesky->getCloudRoot());
stateSet = sceneGroup->getOrCreateStateSet();
- stateSet->setMode(GL_BLEND, osg::StateAttribute::ON);
stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON);
// need to update the light on every frame
- osg::LightSource* lightSource = new osg::LightSource;
- lightSource->setUpdateCallback(new FGLightSourceUpdateCallback);
+ // OSG LightSource objects are rather confusing. OSG only supports
+ // the 10 lights specified by OpenGL itself; if more than one
+ // LightSource in the scene graph have the same light number, it's
+ // indeterminate which values will be used to render geometry that
+ // has that light number enabled. Also, adding children to a
+ // LightSource is just a shortcut for setting up a state set that
+ // 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;
+ 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);
- mRoot->addChild(lightSource);
-
- lightSource->addChild(mBackGroundCamera.get());
- lightSource->addChild(sceneGroup);
-
-
+ lightSource->setUpdateCallback(new FGLightSourceUpdateCallback);
+ mRealRoot->addChild(lightSource);
+ // we need a white diffuse light for the phase of the moon
+ osg::LightSource* sunLight = new osg::LightSource;
+ sunLight->getLight()->setDataVariance(Object::DYNAMIC);
+ sunLight->getLight()->setLightNum(1);
+ sunLight->setUpdateCallback(new FGLightSourceUpdateCallback(true));
+ sunLight->setReferenceFrame(osg::LightSource::RELATIVE_RF);
+ sunLight->setLocalStateSetModes(osg::StateAttribute::ON);
+ // Hang a StateSet above the sky subgraph in order to turn off
+ // light 0
+ Group* skyGroup = new Group;
+ StateSet* skySS = skyGroup->getOrCreateStateSet();
+ skySS->setMode(GL_LIGHT0, StateAttribute::OFF);
+ skyGroup->addChild(thesky->getPreRoot());
+ sunLight->addChild(skyGroup);
+ mRoot->addChild(sceneGroup);
+ mRoot->addChild(sunLight);
+ // Clouds are added to the scene graph later
stateSet = globals->get_scenery()->get_scene_graph()->getOrCreateStateSet();
- stateSet->setMode(GL_BLEND, osg::StateAttribute::ON);
stateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::ON);
stateSet->setMode(GL_LIGHTING, osg::StateAttribute::ON);
stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON);
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, 100);
- guiCamera->setClearMask(0);
- inheritanceMask = osg::CullSettings::ALL_VARIABLES;
- inheritanceMask &= ~osg::CullSettings::COMPUTE_NEAR_FAR_MODE;
- inheritanceMask &= ~osg::CullSettings::CULLING_MODE;
- guiCamera->setInheritanceMask(inheritanceMask);
- guiCamera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
- guiCamera->setCullingMode(osg::CullSettings::NO_CULLING);
- 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());
-
+ osg::Camera* guiCamera = getGUICamera(CameraGroup::getDefault());
+ if (guiCamera) {
+ osg::Geode* geode = new osg::Geode;
+ geode->addDrawable(new SGPuDrawable);
+ geode->addDrawable(new SGHUDAndPanelDrawable);
+ guiCamera->addChild(geode);
+ }
osg::Switch* sw = new osg::Switch;
sw->setUpdateCallback(new FGScenerySwitchCallback);
- sw->addChild(mCameraView.get());
-
+ sw->addChild(mRoot.get());
mRealRoot->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.
+ mRealRoot->addChild(thesky->getCloudRoot());
mRealRoot->addChild(FGCreateRedoutNode());
- mRealRoot->addChild(guiCamera);
+ // 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->setAttributeAndModes(new osg::Program, osg::StateAttribute::ON);
}
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 ) {
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
- sceneView->update();
- sceneView->cull();
- sceneView->draw();
-
+ globals->set_sim_time_sec( 0.0 );
return;
}
SGConfigureDirectionalLights( use_point_sprites, enhanced_lighting,
distance_attenuation );
- static const SGPropertyNode *groundlevel_nearplane
- = fgGetNode("/sim/current-view/ground-level-nearplane-m");
-
FGLight *l = static_cast<FGLight*>(globals->get_subsystem("lighting"));
// update fog params
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.
// update view port
resize( fgGetInt("/sim/startup/xsize"),
fgGetInt("/sim/startup/ysize") );
-
- 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::Camera *camera = viewer->getCamera();
if ( skyblend ) {
+
if ( fgGetBool("/sim/rendering/textures") ) {
SGVec4f clearColor(l->adj_fog_color());
- sceneView->getCamera()->setClearColor(clearColor.osg());
+ camera->setClearColor(toOsg(clearColor));
}
} else {
SGVec4f clearColor(l->sky_color());
- sceneView->getCamera()->setClearColor(clearColor.osg());
+ camera->setClearColor(toOsg(clearColor));
}
// update fog params if visibility has changed
double sun_horiz_eff, moon_horiz_eff;
if (fgGetBool("/sim/rendering/horizon-effect")) {
- sun_horiz_eff = 0.67+pow(0.5+cos(l->get_sun_angle())*2/2, 0.33)/3;
- moon_horiz_eff = 0.67+pow(0.5+cos(l->get_moon_angle())*2/2, 0.33)/3;
+ 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;
}
- static SGSkyState sstate;
-
- 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;
- sstate.lat = current__view->getLatitude_deg()
- * SGD_DEGREES_TO_RADIANS;
- sstate.alt = current__view->getAltitudeASL_ft()
- * SG_FEET_TO_METER;
+ 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_ra = globals->get_ephem()->getSunRightAscension();
- sstate.sun_dec = globals->get_ephem()->getSunDeclination();
sstate.sun_dist = 50000.0 * sun_horiz_eff;
- sstate.moon_ra = globals->get_ephem()->getMoonRightAscension();
- sstate.moon_dec = globals->get_ephem()->getMoonDeclination();
sstate.moon_dist = 40000.0 * moon_horiz_eff;
sstate.sun_angle = l->get_sun_angle();
-
- /*
- SG_LOG( SG_GENERAL, SG_BULK, "thesky->repaint() sky_color = "
- << l->sky_color()[0] << " "
- << l->sky_color()[1] << " "
- << l->sky_color()[2] << " "
- << l->sky_color()[3] );
- SG_LOG( SG_GENERAL, SG_BULK, " fog = "
- << l->fog_color()[0] << " "
- << l->fog_color()[1] << " "
- << l->fog_color()[2] << " "
- << l->fog_color()[3] );
- SG_LOG( SG_GENERAL, SG_BULK,
- " sun_angle = " << l->sun_angle
- << " moon_angle = " << l->moon_angle );
- */
-
- static SGSkyColor scolor;
-
+ 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();
- scolor.nplanets = globals->get_ephem()->getNumPlanets();
- scolor.nstars = globals->get_ephem()->getNumStars();
- scolor.planet_data = globals->get_ephem()->getPlanets();
- scolor.star_data = globals->get_ephem()->getStars();
- thesky->reposition( sstate, delta_time_sec );
- thesky->repaint( scolor );
+ thesky->reposition( sstate, *globals->get_ephem(), delta_time_sec );
+ thesky->repaint( scolor, *globals->get_ephem() );
/*
SG_LOG( SG_GENERAL, SG_BULK,
}
- 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
- glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
-
- double agl = current__view->getAltitudeASL_ft()*SG_FEET_TO_METER
- - current__view->getSGLocation()->get_cur_elev_m();
-
- float scene_nearplane, scene_farplane;
- if ( agl > 10.0 ) {
- scene_nearplane = 10.0f;
- scene_farplane = 120000.0f;
- } else {
- scene_nearplane = groundlevel_nearplane->getDoubleValue();
- scene_farplane = 120000.0f;
- }
- setNearFar( scene_nearplane, scene_farplane );
-
// sgEnviro.startOfFrame(current__view->get_view_pos(),
// current__view->get_world_up(),
// current__view->getLongitude_deg(),
// fgGetDouble("/velocities/airspeed-kt", 0.0)
// * cos( fgGetDouble("/orientation/pitch-deg", 0.0)
// * SGD_DEGREES_TO_RADIANS);
- // TODO:find the real view speed, not the AC one
-// sgEnviro.drawPrecipitation(
-// fgGetDouble("/environment/metar/rain-norm", 0.0),
-// fgGetDouble("/environment/metar/snow-norm", 0.0),
-// fgGetDouble("/environment/metar/hail-norm", 0.0),
-// current__view->getPitch_deg() + current__view->getPitchOffset_deg(),
-// current__view->getRoll_deg() + current__view->getRollOffset_deg(),
-// - current__view->getHeadingOffset_deg(),
-// current_view_origin_airspeed_horiz_kt
-// );
// OSGFIXME
// if( is_internal )
// 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());
mFrameStamp->setCalendarTime(*globals->get_time_params()->getGmt());
mUpdateVisitor->setViewData(current__view->getViewPosition(),
current__view->getViewOrientation());
- mUpdateVisitor->setSceneryCenter(SGVec3d(0, 0, 0));
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();
+ simgear::GroundLightManager::instance()->update(mUpdateVisitor.get());
+ bool hotspots = fgGetBool("/sim/panel-hotspots");
+ osg::Node::NodeMask cullMask = ~simgear::LIGHTS_BITS & ~simgear::PICK_BIT;
+ cullMask |= simgear::GroundLightManager::instance()
+ ->getLightNodeMask(mUpdateVisitor.get());
+ if (hotspots)
+ cullMask |= simgear::PICK_BIT;
+ CameraGroup::getDefault()->setCameraCullMasks(cullMask);
}
view_h = height;
}
- sceneView->getViewport()->setViewport(0, height - view_h, width, view_h);
-
static int lastwidth = 0;
static int lastheight = 0;
if (width != lastwidth)
if (height != lastheight)
fgSetInt("/sim/startup/ysize", lastheight = height);
- guiInitMouse(width, height);
-
// for all views
FGViewMgr *viewmgr = globals->get_viewmgr();
if (viewmgr) {
viewmgr->get_view(i)->
set_aspect_ratio((float)view_h / (float)width);
}
-
- setFOV( viewmgr->get_current_view()->get_h_fov(),
- viewmgr->get_current_view()->get_v_fov() );
}
}
-
-// 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;
+bool
+FGRenderer::pick(std::vector<SGSceneryPick>& pickList,
+ const osgGA::GUIEventAdapter* ea)
+{
+ // wipe out the return ...
+ pickList.clear();
+ typedef osgUtil::LineSegmentIntersector::Intersections Intersections;
+ Intersections intersections;
+
+ if (!computeIntersections(CameraGroup::getDefault(), ea, intersections))
+ return false;
+ for (Intersections::iterator hit = intersections.begin(),
+ e = intersections.end();
+ hit != e;
+ ++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)
+ continue;
+ for (unsigned i = 0; i < ud->getNumPickCallbacks(); ++i) {
+ SGPickCallback* pickCallback = ud->getPickCallback(i);
+ if (!pickCallback)
+ continue;
+ SGSceneryPick sceneryPick;
+ sceneryPick.info.local = toSG(hit->getLocalIntersectPoint());
+ sceneryPick.info.wgs84 = toSG(hit->getWorldIntersectPoint());
+ sceneryPick.callback = pickCallback;
+ pickList.push_back(sceneryPick);
+ }
+ }
}
-
- sceneView->setProjectionMatrixAsFrustum(l, r, b, t, zNear, zFar);
+ return !pickList.empty();
}
-
-// 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
-// interface to the display callback system. There's probably a
-// better way, there has to be a better way, but I'm not seeing it
-// right now.
-static float fov_width = 55.0;
-static float fov_height = 42.0;
-static float fov_near = 1.0;
-static float fov_far = 1000.0;
-
-
-/** FlightGear code should use this routine to set the FOV rather than
- * calling the ssg routine directly
- */
-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 );
+void
+FGRenderer::setViewer(osgViewer::Viewer* viewer_)
+{
+ viewer = viewer_;
}
+void
+FGRenderer::setEventHandler(FGEventHandler* eventHandler_)
+{
+ eventHandler = eventHandler_;
+}
-/** FlightGear code should use this routine to set the Near/Far clip
- * planes rather than calling the ssg routine directly
- */
-void FGRenderer::setNearFar( float n, float f ) {
-// OSGFIXME: we have currently too much z-buffer fights
-n = 0.1;
- fov_near = n;
- fov_far = f;
-
- 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();
+void
+FGRenderer::addCamera(osg::Camera* camera, bool useSceneData)
+{
+ mRealRoot->addChild(camera);
}
bool
-FGRenderer::pick( unsigned x, unsigned y,
- std::vector<SGSceneryPick>& pickList )
+fgDumpSceneGraphToFile(const char* filename)
{
- // wipe out the return ...
- pickList.resize(0);
-
- // we can get called early ...
- if (!sceneView.valid())
- return false;
-
- 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 osgDB::writeNodeFile(*mRealRoot.get(), filename);
+}
- return !pickList.empty();
+bool
+fgDumpTerrainBranchToFile(const char* filename)
+{
+ return osgDB::writeNodeFile( *globals->get_scenery()->get_terrain_branch(),
+ filename );
}
+// For debugging
+bool
+fgDumpNodeToFile(osg::Node* node, const char* filename)
+{
+ return osgDB::writeNodeFile(*node, filename);
+}
// end of renderer.cxx