//
// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// $Id$
# include <windows.h>
#endif
-#include <plib/ssg.h>
-#include <plib/netSocket.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/Light>
+#include <osg/LightModel>
+#include <osg/LightSource>
+#include <osg/NodeCallback>
+#include <osg/Notify>
+#include <osg/PolygonMode>
+#include <osg/PolygonOffset>
+#include <osg/ShadeModel>
+#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/util/SGUpdateVisitor.hxx>
+#include <simgear/scene/tgdb/pt_lights.hxx>
#include <simgear/props/props.hxx>
#include <simgear/timing/sg_time.hxx>
-#include <simgear/scene/model/animation.hxx>
#include <simgear/ephemeris/ephemeris.hxx>
-#include <simgear/scene/model/placement.hxx>
#include <simgear/math/sg_random.h>
-#include <simgear/scene/model/modellib.hxx>
-#include <simgear/scene/model/model.hxx>
#ifdef FG_JPEG_SERVER
#include <simgear/screen/jpgfactory.hxx>
#endif
#include <Model/modelmgr.hxx>
#include <Model/acmodel.hxx>
#include <Scenery/scenery.hxx>
+#include <Scenery/redout.hxx>
#include <Scenery/tilemgr.hxx>
-#include <ATC/ATCdisplay.hxx>
-#include <Replay/replay.hxx>
#include <GUI/new_gui.hxx>
+#include <Instrumentation/instrument_mgr.hxx>
+#include <Instrumentation/HUD/HUD.hxx>
#include "splash.hxx"
#include "renderer.hxx"
#include "main.hxx"
+class SGPuDrawable : public osg::Drawable {
+public:
+ SGPuDrawable()
+ {
+ // Dynamic stuff, do not store geometry
+ setUseDisplayList(false);
+
+ osg::StateSet* stateSet = getOrCreateStateSet();
+ stateSet->setRenderBinDetails(1001, "RenderBin");
+ // speed optimization?
+ stateSet->setMode(GL_CULL_FACE, osg::StateAttribute::OFF);
+ // We can do translucent menus, so why not. :-)
+ stateSet->setAttribute(new osg::BlendFunc(osg::BlendFunc::SRC_ALPHA, osg::BlendFunc::ONE_MINUS_SRC_ALPHA));
+ stateSet->setMode(GL_BLEND, osg::StateAttribute::ON);
+ stateSet->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::OFF);
+
+ stateSet->setTextureAttribute(0, new osg::TexEnv(osg::TexEnv::MODULATE));
+
+ stateSet->setMode(GL_FOG, osg::StateAttribute::OFF);
+ stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
+ }
+ virtual void drawImplementation(osg::RenderInfo& renderInfo) const
+ { drawImplementation(*renderInfo.getState()); }
+ void drawImplementation(osg::State& state) const
+ {
+ if (!fgOSIsMainContext(state.getGraphicsContext()))
+ return;
+
+ state.pushStateSet(getStateSet());
+ state.apply();
+ state.setActiveTextureUnit(0);
+ state.setClientActiveTextureUnit(0);
+ state.disableAllVertexArrays();
+
+ glPushAttrib(GL_ALL_ATTRIB_BITS);
+ glPushClientAttrib(~0u);
+
+ puDisplay();
+
+ glPopClientAttrib();
+ glPopAttrib();
+
+ state.popStateSet();
+ state.dirtyAllModes();
+ state.dirtyAllAttributes();
+ state.dirtyAllVertexArrays();
+ }
+
+ virtual osg::Object* cloneType() const { return new SGPuDrawable; }
+ virtual osg::Object* clone(const osg::CopyOp&) const { return new SGPuDrawable; }
+
+private:
+};
+
+class SGHUDAndPanelDrawable : public osg::Drawable {
+public:
+ SGHUDAndPanelDrawable()
+ {
+ // Dynamic stuff, do not store geometry
+ setUseDisplayList(false);
+
+ osg::StateSet* stateSet = 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);
+
+ stateSet->setTextureAttribute(0, new osg::TexEnv(osg::TexEnv::MODULATE));
+ }
+ virtual void drawImplementation(osg::RenderInfo& renderInfo) const
+ { drawImplementation(*renderInfo.getState()); }
+ void drawImplementation(osg::State& state) const
+ {
+// std::cout << state.getGraphicsContext() << std::endl;
+ if (!fgOSIsMainContext(state.getGraphicsContext()))
+ return;
+
+ state.pushStateSet(getStateSet());
+ state.apply();
+ state.setActiveTextureUnit(0);
+ state.setClientActiveTextureUnit(0);
+ state.disableAllVertexArrays();
+
+ glPushAttrib(GL_ALL_ATTRIB_BITS);
+ glPushClientAttrib(~0u);
+
+ fgCockpitUpdate(&state);
+
+ FGInstrumentMgr *instr = static_cast<FGInstrumentMgr*>(globals->get_subsystem("instrumentation"));
+ HUD *hud = static_cast<HUD*>(instr->get_subsystem("hud"));
+ hud->draw(state);
+
+ // update the panel subsystem
+ if ( globals->get_current_panel() != NULL )
+ globals->get_current_panel()->update(state);
+ // We don't need a state here - can be safely removed when we can pick
+ // correctly
+ fgUpdate3DPanels();
+
+ glPopClientAttrib();
+ glPopAttrib();
-float default_attenuation[3] = {1.0, 0.0, 0.0};
+ state.popStateSet();
+ state.dirtyAllModes();
+ state.dirtyAllAttributes();
+ state.dirtyAllVertexArrays();
+ }
+
+ virtual osg::Object* cloneType() const { return new SGHUDAndPanelDrawable; }
+ virtual osg::Object* clone(const osg::CopyOp&) const { return new SGHUDAndPanelDrawable; }
+
+private:
+};
+
+class FGLightSourceUpdateCallback : public osg::NodeCallback {
+public:
+ virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
+ {
+ assert(dynamic_cast<osg::LightSource*>(node));
+ osg::LightSource* lightSource = static_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);
+
+ traverse(node, nv);
+ }
+};
+
+class FGWireFrameModeUpdateCallback : public osg::StateAttribute::Callback {
+public:
+ FGWireFrameModeUpdateCallback() :
+ mWireframe(fgGetNode("/sim/rendering/wireframe"))
+ { }
+ virtual void operator()(osg::StateAttribute* stateAttribute,
+ osg::NodeVisitor*)
+ {
+ assert(dynamic_cast<osg::PolygonMode*>(stateAttribute));
+ osg::PolygonMode* polygonMode;
+ polygonMode = static_cast<osg::PolygonMode*>(stateAttribute);
+
+ if (mWireframe->getBoolValue())
+ polygonMode->setMode(osg::PolygonMode::FRONT_AND_BACK,
+ osg::PolygonMode::LINE);
+ else
+ polygonMode->setMode(osg::PolygonMode::FRONT_AND_BACK,
+ osg::PolygonMode::FILL);
+ }
+private:
+ SGSharedPtr<SGPropertyNode> mWireframe;
+};
+
+class FGLightModelUpdateCallback : public osg::StateAttribute::Callback {
+public:
+ FGLightModelUpdateCallback() :
+ mHighlights(fgGetNode("/sim/rendering/specular-highlight"))
+ { }
+ virtual void operator()(osg::StateAttribute* stateAttribute,
+ osg::NodeVisitor*)
+ {
+ assert(dynamic_cast<osg::LightModel*>(stateAttribute));
+ osg::LightModel* lightModel;
+ lightModel = static_cast<osg::LightModel*>(stateAttribute);
+
+#if 0
+ FGLight *l = static_cast<FGLight*>(globals->get_subsystem("lighting"));
+ lightModel->setAmbientIntensity(l->scene_ambient().osg());
+#else
+ lightModel->setAmbientIntensity(osg::Vec4(0, 0, 0, 1));
+#endif
+ lightModel->setTwoSided(true);
+ lightModel->setLocalViewer(false);
-ssgSelector *lightpoints_brightness = new ssgSelector;
-ssgTransform *lightpoints_transform = new ssgTransform;
-FGTileEntry *dummy_tile;
-sgVec3 rway_ols;
+ if (mHighlights->getBoolValue()) {
+ lightModel->setColorControl(osg::LightModel::SEPARATE_SPECULAR_COLOR);
+ } else {
+ lightModel->setColorControl(osg::LightModel::SINGLE_COLOR);
+ }
+ }
+private:
+ SGSharedPtr<SGPropertyNode> mHighlights;
+};
-// Clip plane settings...
-float scene_nearplane = 0.5f;
-float scene_farplane = 120000.0f;
+class FGFogEnableUpdateCallback : public osg::StateSet::Callback {
+public:
+ FGFogEnableUpdateCallback() :
+ mFogEnabled(fgGetNode("/sim/rendering/fog"))
+ { }
+ virtual void operator()(osg::StateSet* stateSet, osg::NodeVisitor*)
+ {
+ if (strcmp(mFogEnabled->getStringValue(), "disabled") == 0) {
+ stateSet->setMode(GL_FOG, osg::StateAttribute::OFF);
+ } else {
+ stateSet->setMode(GL_FOG, osg::StateAttribute::ON);
+ }
+ }
+private:
+ SGSharedPtr<SGPropertyNode> mFogEnabled;
+};
-glPointParameterfProc glPointParameterfPtr = 0;
-glPointParameterfvProc glPointParameterfvPtr = 0;
-bool glPointParameterIsSupported = false;
+class FGFogUpdateCallback : public osg::StateAttribute::Callback {
+public:
+ virtual void operator () (osg::StateAttribute* sa, osg::NodeVisitor* nv)
+ {
+ assert(dynamic_cast<SGUpdateVisitor*>(nv));
+ assert(dynamic_cast<osg::Fog*>(sa));
+ SGUpdateVisitor* updateVisitor = static_cast<SGUpdateVisitor*>(nv);
+ osg::Fog* fog = static_cast<osg::Fog*>(sa);
+ fog->setMode(osg::Fog::EXP2);
+ fog->setColor(updateVisitor->getFogColor().osg());
+ fog->setDensity(updateVisitor->getFogExp2Density());
+ }
+};
+// update callback for the switch node guarding that splash
+class FGScenerySwitchCallback : public osg::NodeCallback {
+public:
+ virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
+ {
+ assert(dynamic_cast<osg::Switch*>(node));
+ osg::Switch* sw = static_cast<osg::Switch*>(node);
-// 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;
+ double t = globals->get_sim_time_sec();
+ bool enabled = 0 < t;
+ sw->setValue(0, enabled);
+ if (!enabled)
+ return;
+ traverse(node, nv);
+ }
+};
// Sky structures
SGSky *thesky;
-// hack
-sgMat4 copy_of_ssgOpenGLAxisSwapMatrix =
-{
- { 1.0f, 0.0f, 0.0f, 0.0f },
- { 0.0f, 0.0f, -1.0f, 0.0f },
- { 0.0f, 1.0f, 0.0f, 0.0f },
- { 0.0f, 0.0f, 0.0f, 1.0f }
-};
+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> mRealRoot = new osg::Group;
-ssgSimpleState *cloud3d_imposter_state;
-ssgSimpleState *default_state;
-ssgSimpleState *hud_and_panel;
-ssgSimpleState *menus;
+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;
FGRenderer::FGRenderer()
{
#ifdef FG_JPEG_SERVER
jpgRenderFrame = FGRenderer::update;
#endif
+#ifdef ENABLE_OSGVIEWER
+ manipulator = new FGManipulator;
+#endif
}
FGRenderer::~FGRenderer()
#endif
}
-
+// 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::build_states( void ) {
- default_state = new ssgSimpleState;
- default_state->ref();
- default_state->disable( GL_TEXTURE_2D );
- default_state->enable( GL_CULL_FACE );
- default_state->enable( GL_COLOR_MATERIAL );
- default_state->setColourMaterial( GL_AMBIENT_AND_DIFFUSE );
- default_state->setMaterial( GL_EMISSION, 0, 0, 0, 1 );
- default_state->setMaterial( GL_SPECULAR, 0, 0, 0, 1 );
- default_state->disable( GL_BLEND );
- default_state->disable( GL_ALPHA_TEST );
- default_state->disable( GL_LIGHTING );
-
- cloud3d_imposter_state = new ssgSimpleState;
- cloud3d_imposter_state->ref();
- cloud3d_imposter_state->enable( GL_TEXTURE_2D );
- cloud3d_imposter_state->enable( GL_CULL_FACE );
- cloud3d_imposter_state->enable( GL_COLOR_MATERIAL );
- cloud3d_imposter_state->setColourMaterial( GL_AMBIENT_AND_DIFFUSE );
- cloud3d_imposter_state->setMaterial( GL_DIFFUSE, 1, 1, 1, 1 );
- cloud3d_imposter_state->setMaterial( GL_AMBIENT, 1, 1, 1, 1 );
- cloud3d_imposter_state->setMaterial( GL_EMISSION, 0, 0, 0, 1 );
- cloud3d_imposter_state->setMaterial( GL_SPECULAR, 0, 0, 0, 1 );
- cloud3d_imposter_state->enable( GL_BLEND );
- cloud3d_imposter_state->enable( GL_ALPHA_TEST );
- cloud3d_imposter_state->disable( GL_LIGHTING );
-
- hud_and_panel = new ssgSimpleState;
- hud_and_panel->ref();
- hud_and_panel->disable( GL_CULL_FACE );
- hud_and_panel->disable( GL_TEXTURE_2D );
- hud_and_panel->disable( GL_LIGHTING );
- hud_and_panel->enable( GL_BLEND );
-
- menus = new ssgSimpleState;
- menus->ref();
- menus->disable( GL_CULL_FACE );
- menus->disable( GL_TEXTURE_2D );
- menus->enable( GL_BLEND );
+FGRenderer::splashinit( void ) {
+ osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
+ if (viewer) {
+ sceneView = 0;
+ mRealRoot = dynamic_cast<osg::Group*>(viewer->getSceneData());
+ mRealRoot->addChild(fgCreateSplashNode());
+ osgViewer::Scene* scene = viewer->getScene();
+ mFrameStamp = viewer->getFrameStamp();
+ // Scene doesn't seem to pass the frame stamp to the update
+ // visitor automatically.
+ mUpdateVisitor->setFrameStamp(mFrameStamp.get());
+ scene->setUpdateVisitor(mUpdateVisitor.get());
+ } else {
+ // Add the splash screen node
+ mRealRoot->addChild(fgCreateSplashNode());
+ sceneView->setSceneData(mRealRoot.get());
+ sceneView->setDefaults(osgUtil::SceneView::COMPILE_GLOBJECTS_AT_INIT);
+ sceneView->setFrameStamp(mFrameStamp.get());
+ sceneView->setUpdateVisitor(mUpdateVisitor.get());
+ }
}
-
-// Initialize various GL/view parameters
void
FGRenderer::init( void ) {
-
- FGLight *l = (FGLight *)(globals->get_subsystem("lighting"));
+ // The viewer can call this before the graphics context is current
+ // in the main thread; indeed, in a multithreaded setup it might
+ // never be current in the main thread.
+ fgMakeCurrent();
+ osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
+ osg::initNotifyLevel();
+
+ // The number of polygon-offset "units" to place between layers. In
+ // 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);
// Go full screen if requested ...
- if ( fgGetBool("/sim/startup/fullscreen") ) {
+ if ( fgGetBool("/sim/startup/fullscreen") )
fgOSFullScreen();
- }
-
- // If enabled, normal vectors specified with glNormal are scaled
- // to unit length after transformation. Enabling this has
- // performance implications. See the docs for glNormal.
- // glEnable( GL_NORMALIZE );
-
- glEnable( GL_LIGHTING );
- glEnable( GL_LIGHT0 );
- // glLightfv( GL_LIGHT0, GL_POSITION, l->sun_vec ); // done later with ssg
- sgVec3 sunpos;
- sgSetVec3( sunpos, l->sun_vec()[0], l->sun_vec()[1], l->sun_vec()[2] );
- ssgGetLight( 0 ) -> setPosition( sunpos );
-
- glFogi (GL_FOG_MODE, GL_EXP2);
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_NICEST );
+ glHint ( GL_FOG_HINT, GL_DONT_CARE );
}
- if ( fgGetBool("/sim/rendering/wireframe") ) {
- // draw wire frame
- glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
+
+ glHint(GL_POLYGON_SMOOTH_HINT, GL_DONT_CARE);
+ glHint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE);
+ glHint(GL_POINT_SMOOTH_HINT, GL_DONT_CARE);
+
+ if (viewer) {
+ viewer->getCamera()
+ ->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
+ } else {
+ sceneView->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
+ sceneView->getCamera()->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
}
- // This is the default anyways, but it can't hurt
- glFrontFace ( GL_CCW );
- // Just testing ...
- // glEnable(GL_POINT_SMOOTH);
- // glEnable(GL_LINE_SMOOTH);
- // glEnable(GL_POLYGON_SMOOTH);
+ osg::StateSet* stateSet = mRoot->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);
+
+
+// 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::Group* sceneGroup = new osg::Group;
+ sceneGroup->addChild(globals->get_scenery()->get_scene_graph());
+ 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);
+ // 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);
+
+
+ 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);
+
+ // enable disable specular highlights.
+ // is the place where we might plug in an other fragment shader ...
+ osg::LightModel* lightModel = new osg::LightModel;
+ lightModel->setUpdateCallback(new FGLightModelUpdateCallback);
+ stateSet->setAttribute(lightModel);
+
+ // switch to enable wireframe
+ osg::PolygonMode* polygonMode = new osg::PolygonMode;
+ polygonMode->setUpdateCallback(new FGWireFrameModeUpdateCallback);
+ stateSet->setAttributeAndModes(polygonMode);
+
+ // scene fog handling
+ 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);
+
+ mCameraView->addChild(mRoot.get());
+
+ osg::Switch* sw = new osg::Switch;
+ sw->setUpdateCallback(new FGScenerySwitchCallback);
+ sw->addChild(mCameraView.get());
+
+ mRealRoot->addChild(sw);
+ mRealRoot->addChild(FGCreateRedoutNode());
+ mRealRoot->addChild(guiCamera);
+// sceneView->getState()->setCheckForGLErrors(osg::State::ONCE_PER_ATTRIBUTE);
}
-
// Update all Visuals (redraws anything graphics related)
void
FGRenderer::update( bool refresh_camera_settings ) {
- bool scenery_loaded = fgGetBool("sim/sceneryloaded") || fgGetBool("sim/sceneryloaded-override");
-
+ bool scenery_loaded = fgGetBool("sim/sceneryloaded")
+ || fgGetBool("sim/sceneryloaded-override");
+ osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
if ( idle_state < 1000 || !scenery_loaded ) {
- // still initializing, draw the splash screen
- fgSplashUpdate(1.0);
+ fgSetDouble("/sim/startup/splash-alpha", 1.0);
// Keep resetting sim time while the sim is initializing
globals->set_sim_time_sec( 0.0 );
- SGAnimation::set_sim_time_sec( 0.0 );
+
+ // the splash screen is now in the scenegraph
+ if (!viewer) {
+ sceneView->update();
+ sceneView->cull();
+ sceneView->draw();
+ }
return;
}
+ // Fade out the splash screen over the first three seconds.
+ double sAlpha = SGMiscd::max(0, (2.5 - globals->get_sim_time_sec()) / 2.5);
+ fgSetDouble("/sim/startup/splash-alpha", sAlpha);
- bool draw_otw = fgGetBool("/sim/rendering/draw-otw");
bool skyblend = fgGetBool("/sim/rendering/skyblend");
+ bool use_point_sprites = fgGetBool("/sim/rendering/point-sprites");
bool enhanced_lighting = fgGetBool("/sim/rendering/enhanced-lighting");
- bool distance_attenuation = fgGetBool("/sim/rendering/distance-attenuation");
- bool volumetric_clouds = sgEnviro.get_clouds_enable_state();
-#ifdef FG_ENABLE_MULTIPASS_CLOUDS
- bool multi_pass_clouds = fgGetBool("/sim/rendering/multi-pass-clouds") &&
- !volumetric_clouds &&
- !SGCloudLayer::enable_bump_mapping; // ugly artefact now
-#else
- bool multi_pass_clouds = false;
-#endif
- bool draw_clouds = fgGetBool("/environment/clouds/status");
-
- GLfloat black[4] = { 0.0, 0.0, 0.0, 1.0 };
- GLfloat white[4] = { 1.0, 1.0, 1.0, 1.0 };
+ bool distance_attenuation
+ = fgGetBool("/sim/rendering/distance-attenuation");
+ // OSGFIXME
+ SGConfigureDirectionalLights( use_point_sprites, enhanced_lighting,
+ distance_attenuation );
- // static const SGPropertyNode *longitude
- // = fgGetNode("/position/longitude-deg");
- // static const SGPropertyNode *latitude
- // = fgGetNode("/position/latitude-deg");
- // static const SGPropertyNode *altitude
- // = fgGetNode("/position/altitude-ft");
static const SGPropertyNode *groundlevel_nearplane
= fgGetNode("/sim/current-view/ground-level-nearplane-m");
- FGLight *l = (FGLight *)(globals->get_subsystem("lighting"));
- static double last_visibility = -9999;
+ FGLight *l = static_cast<FGLight*>(globals->get_subsystem("lighting"));
// update fog params
double actual_visibility;
actual_visibility = fgGetDouble("/environment/visibility-m");
}
- 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 );
- }
- }
-
- // double angle;
- // GLfloat black[4] = { 0.0, 0.0, 0.0, 1.0 };
- // GLfloat white[4] = { 1.0, 1.0, 1.0, 1.0 };
- // GLfloat terrain_color[4] = { 0.54, 0.44, 0.29, 1.0 };
- // GLfloat mat_shininess[] = { 10.0 };
- GLbitfield clear_mask;
-
// 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.
FGViewer *current__view = globals->get_current_view();
-
- // calculate our current position in cartesian space
- Point3D cntr = globals->get_scenery()->get_next_center();
- globals->get_scenery()->set_center(cntr);
- current__view->set_scenery_center(cntr);
+ // Force update of center dependent values ...
+ current__view->set_dirty();
if ( refresh_camera_settings ) {
// update view port
resize( fgGetInt("/sim/startup/xsize"),
fgGetInt("/sim/startup/ysize") );
- // Tell GL we are switching to model view parameters
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- ssgSetCamera( (sgVec4 *)current__view->get_VIEW() );
+ SGVec3d position = current__view->getViewPosition();
+ SGQuatd attitude = current__view->getViewOrientation();
+ SGVec3d osgPosition = attitude.transform(-position);
+ if (viewer) {
+ FGManipulator *manipulator
+ = globals->get_renderer()->getManipulator();
+ manipulator->setPosition(position.osg());
+ manipulator->setAttitude(attitude.osg());
+ } else {
+ mCameraView->setPosition(osgPosition.osg());
+ mCameraView->setAttitude(inverse(attitude).osg());
+ }
}
-
- clear_mask = GL_DEPTH_BUFFER_BIT;
- if ( fgGetBool("/sim/rendering/wireframe") ) {
- clear_mask |= GL_COLOR_BUFFER_BIT;
- }
-
+ osg::Camera *camera;
+ if (viewer)
+ camera = viewer->getCamera();
+ else
+ camera = sceneView->getCamera();
if ( skyblend ) {
+
if ( fgGetBool("/sim/rendering/textures") ) {
- // glClearColor(black[0], black[1], black[2], black[3]);
- glClearColor(l->adj_fog_color()[0], l->adj_fog_color()[1],
- l->adj_fog_color()[2], l->adj_fog_color()[3]);
- clear_mask |= GL_COLOR_BUFFER_BIT;
+ SGVec4f clearColor(l->adj_fog_color());
+ camera->setClearColor(clearColor.osg());
}
} else {
- glClearColor(l->sky_color()[0], l->sky_color()[1],
- l->sky_color()[2], l->sky_color()[3]);
- clear_mask |= GL_COLOR_BUFFER_BIT;
- }
- if ( multi_pass_clouds && draw_clouds ) {
- glClearStencil( 0 );
- clear_mask |= GL_STENCIL_BUFFER_BIT;
+ SGVec4f clearColor(l->sky_color());
+ camera->setClearColor(clearColor.osg());
}
- glClear( clear_mask );
-
- // set the opengl state to known default values
- default_state->force();
// update fog params if visibility has changed
double visibility_meters = fgGetDouble("/environment/visibility-m");
( global_multi_loop * fgGetInt("/sim/speed-up") )
/ (double)fgGetInt("/sim/model-hz") );
- // Set correct opengl fog density
- glFogf (GL_FOG_DENSITY, fog_exp2_density);
-
// 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 (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;
+ } 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;
+ 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->fog_color()[0] << " "
<< l->fog_color()[1] << " "
<< l->fog_color()[2] << " "
- << l->fog_color()[3] );
+ << l->fog_color()[3] );
SG_LOG( SG_GENERAL, SG_BULK,
" sun_angle = " << l->sun_angle
<< " moon_angle = " << l->moon_angle );
*/
static SGSkyColor scolor;
- FGLight *l = (FGLight *)(globals->get_subsystem("lighting"));
- scolor.sky_color = l->sky_color();
- scolor.fog_color = l->adj_fog_color();
- scolor.cloud_color = l->cloud_color();
+ scolor.sky_color = SGVec3f(l->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.planet_data = globals->get_ephem()->getPlanets();
scolor.star_data = globals->get_ephem()->getStars();
+ thesky->reposition( sstate, delta_time_sec );
thesky->repaint( scolor );
/*
<< " moon dec = " << globals->get_ephem()->getMoonDeclination() );
*/
- // 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 (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;
- } else {
- sun_horiz_eff = moon_horiz_eff = 1.0;
- }
-
- static SGSkyState sstate;
-
- sstate.view_pos = current__view->get_view_pos();
- sstate.zero_elev = 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;
- 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;
-
- thesky->reposition( sstate, delta_time_sec );
- }
+ //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());
- glEnable( GL_DEPTH_TEST );
- if ( strcmp(fgGetString("/sim/rendering/fog"), "disabled") ) {
- glEnable( GL_FOG );
- glFogi( GL_FOG_MODE, GL_EXP2 );
- glFogfv( GL_FOG_COLOR, l->adj_fog_color() );
}
- // set sun/lighting parameters
- ssgGetLight( 0 ) -> setPosition( l->sun_vec() );
-
- // GL_LIGHT_MODEL_AMBIENT has a default non-zero value so if
- // we only update GL_AMBIENT for our lights we will never get
- // a completely dark scene. So, we set GL_LIGHT_MODEL_AMBIENT
- // explicitely to black.
- glLightModelfv( GL_LIGHT_MODEL_AMBIENT, black );
-
- ssgGetLight( 0 ) -> setColour( GL_AMBIENT, l->scene_ambient() );
- ssgGetLight( 0 ) -> setColour( GL_DIFFUSE, l->scene_diffuse() );
- ssgGetLight( 0 ) -> setColour( GL_SPECULAR, l->scene_specular() );
-
- sgEnviro.setLight(l->adj_fog_color());
+// sgEnviro.setLight(l->adj_fog_color());
// texture parameters
- // glEnable( GL_TEXTURE_2D );
- glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ) ;
- glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST ) ;
+ glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
- double agl =
- current_aircraft.fdm_state->get_Altitude() * SG_FEET_TO_METER
- - globals->get_scenery()->get_cur_elev();
+ double agl = current__view->getAltitudeASL_ft()*SG_FEET_TO_METER
+ - current__view->getSGLocation()->get_cur_elev_m();
- if ( agl > 50.0 ) {
+ 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(),
- current__view->getLatitude_deg(),
- current__view->getAltitudeASL_ft() * SG_FEET_TO_METER,
- delta_time_sec);
-
- if ( draw_otw && skyblend ) {
- // draw the sky backdrop
-
- // we need a white diffuse light for the phase of the moon
- ssgGetLight( 0 ) -> setColour( GL_DIFFUSE, white );
- thesky->preDraw( cur_fdm_state->get_Altitude() * SG_FEET_TO_METER,
- fog_exp2_density );
- // return to the desired diffuse color
- ssgGetLight( 0 ) -> setColour( GL_DIFFUSE, l->scene_diffuse() );
- }
-
- // draw the ssg scene
- glEnable( GL_DEPTH_TEST );
-
- if ( fgGetBool("/sim/rendering/wireframe") ) {
- // draw wire frame
- glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
- }
- if ( draw_otw ) {
- if ( draw_clouds ) {
-
- // Draw the terrain
- FGTileMgr::set_tile_filter( true );
- sgSetModelFilter( false );
- globals->get_aircraft_model()->select( false );
- ssgCullAndDraw( globals->get_scenery()->get_scene_graph() );
-
- // Disable depth buffer update, draw the clouds
- glDepthMask( GL_FALSE );
- if( !volumetric_clouds )
- thesky->drawUpperClouds();
- if ( multi_pass_clouds ) {
- thesky->drawLowerClouds();
- }
- glDepthMask( GL_TRUE );
-
- if ( multi_pass_clouds ) {
- // Draw the objects except the aircraft
- // and update the stencil buffer with 1
- glEnable( GL_STENCIL_TEST );
- glStencilFunc( GL_ALWAYS, 1, 1 );
- glStencilOp( GL_KEEP, GL_KEEP, GL_REPLACE );
- }
- FGTileMgr::set_tile_filter( false );
- sgSetModelFilter( true );
- ssgCullAndDraw( globals->get_scenery()->get_scene_graph() );
- } else {
- FGTileMgr::set_tile_filter( true );
- sgSetModelFilter( true );
- globals->get_aircraft_model()->select( false );
- ssgCullAndDraw( globals->get_scenery()->get_scene_graph() );
- }
- }
-
- // This is a bit kludgy. Every 200 frames, do an extra
- // traversal of the scene graph without drawing anything, but
- // with the field-of-view set to 360x360 degrees. This
- // ensures that out-of-range random objects that are not in
- // the current view frustum will still be freed properly.
- static int counter = 0;
- counter++;
- if (counter >= 200) {
- sgFrustum f;
- f.setFOV(360, 360);
- // No need to put the near plane too close;
- // this way, at least the aircraft can be
- // culled.
- f.setNearFar(1000, 1000000);
- sgMat4 m;
- ssgGetModelviewMatrix(m);
- FGTileMgr::set_tile_filter( true );
- sgSetModelFilter( true );
- globals->get_scenery()->get_scene_graph()->cull(&f, m, true);
- counter = 0;
- }
-
- // change state for lighting here
-
- // draw runway lighting
- glFogf (GL_FOG_DENSITY, rwy_exp2_punch_through);
-
- // CLO - 02/25/2005 - DO WE NEED THIS extra fgSetNearFar()?
- // fgSetNearFar( scene_nearplane, scene_farplane );
-
- if ( enhanced_lighting ) {
-
- // Enable states for drawing points with GL_extension
- glEnable(GL_POINT_SMOOTH);
-
- if ( distance_attenuation && glPointParameterIsSupported )
- {
- // Enable states for drawing points with GL_extension
- glEnable(GL_POINT_SMOOTH);
-
- float quadratic[3] = {1.0, 0.001, 0.0000001};
- // makes the points fade as they move away
- glPointParameterfvPtr(GL_DISTANCE_ATTENUATION_EXT, quadratic);
- glPointParameterfPtr(GL_POINT_SIZE_MIN_EXT, 1.0);
- }
-
- glPointSize(4.0);
-
- // blending function for runway lights
- glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) ;
- }
-
- glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
- glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
- glEnable(GL_TEXTURE_GEN_S);
- glEnable(GL_TEXTURE_GEN_T);
- glPolygonMode(GL_FRONT, GL_POINT);
-
- // draw runway lighting
- if ( draw_otw ) {
- ssgCullAndDraw( globals->get_scenery()->get_vasi_lights_root() );
- ssgCullAndDraw( globals->get_scenery()->get_rwy_lights_root() );
- }
-
- // change punch through and then draw taxi lighting
- glFogf ( GL_FOG_DENSITY, fog_exp2_density );
- // sgVec3 taxi_fog;
- // sgSetVec3( taxi_fog, 0.0, 0.0, 0.0 );
- // glFogfv ( GL_FOG_COLOR, taxi_fog );
- if ( draw_otw ) {
- ssgCullAndDraw( globals->get_scenery()->get_taxi_lights_root() );
- }
-
- // clean up lighting
- glPolygonMode(GL_FRONT, GL_FILL);
- glDisable(GL_TEXTURE_GEN_S);
- glDisable(GL_TEXTURE_GEN_T);
-
- //static int _frame_count = 0;
- //if (_frame_count % 30 == 0) {
- // printf("SSG: %s\n", ssgShowStats());
- //}
- //else {
- // ssgShowStats();
- //}
- //_frame_count++;
-
-
- if ( enhanced_lighting ) {
- if ( distance_attenuation && glPointParameterIsSupported ) {
- glPointParameterfvPtr(GL_DISTANCE_ATTENUATION_EXT,
- default_attenuation);
- }
-
- glPointSize(1.0);
- glDisable(GL_POINT_SMOOTH);
- }
-
- // draw ground lighting
- glFogf (GL_FOG_DENSITY, ground_exp2_punch_through);
- if ( draw_otw ) {
- ssgCullAndDraw( globals->get_scenery()->get_gnd_lights_root() );
- }
-
- sgEnviro.drawLightning();
-
- if ( draw_otw && draw_clouds ) {
- if ( multi_pass_clouds ) {
- // Disable depth buffer update, draw the clouds where the
- // objects overwrite the already drawn clouds, by testing
- // the stencil buffer against 1
- glDepthMask( GL_FALSE );
- glStencilFunc( GL_EQUAL, 1, 1 );
- glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
- thesky->drawUpperClouds();
- thesky->drawLowerClouds();
- glDepthMask( GL_TRUE );
- glDisable( GL_STENCIL_TEST );
- } else {
- glDepthMask( GL_FALSE );
- if( volumetric_clouds )
- thesky->drawUpperClouds();
- thesky->drawLowerClouds();
- glDepthMask( GL_TRUE );
- }
+// 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);
+ // 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
+ if (!viewer) {
+ mFrameStamp->setReferenceTime(globals->get_sim_time_sec());
+ mFrameStamp->setSimulationTime(globals->get_sim_time_sec());
+ mFrameStamp->setFrameNumber(1+mFrameStamp->getFrameNumber());
}
- 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(),
- fgGetDouble("/velocities/airspeed-kt", 0.0));
-
- if ( draw_otw ) {
- FGTileMgr::set_tile_filter( false );
- sgSetModelFilter( false );
- globals->get_aircraft_model()->select( true );
- globals->get_model_mgr()->draw();
- globals->get_aircraft_model()->draw();
- // If the view is internal, the previous line draw the
- // cockpit with modified near/far clip planes and deselect
- // the aircraft in the global scenegraph
- // Otherwise, it just enables the aircraft: The scenegraph
- // must be drawn again to see the plane.
- ssgCullAndDraw( globals->get_scenery()->get_scene_graph() );
- FGTileMgr::set_tile_filter( true );
- sgSetModelFilter( true );
- globals->get_aircraft_model()->select( true );
- }
-
- // display HUD && Panel
- glDisable( GL_FOG );
- glDisable( GL_DEPTH_TEST );
- // glDisable( GL_CULL_FACE );
- // glDisable( GL_TEXTURE_2D );
-
- // update the controls subsystem
- globals->get_controls()->update(delta_time_sec);
-
- hud_and_panel->apply();
- fgCockpitUpdate();
-
- // Use the hud_and_panel ssgSimpleState for rendering the ATC output
- // This only works properly if called before the panel call
- if((fgGetBool("/sim/atc/enabled")) || (fgGetBool("/sim/ai-traffic/enabled")))
- globals->get_ATC_display()->update(delta_time_sec);
-
- // update the panel subsystem
- if ( globals->get_current_panel() != NULL ) {
- globals->get_current_panel()->update(delta_time_sec);
+ mFrameStamp->setCalendarTime(*globals->get_time_params()->getGmt());
+ mUpdateVisitor->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(),
+ l->scene_diffuse(), l->scene_specular(),
+ l->adj_fog_color(),
+ l->get_sun_angle()*SGD_RADIANS_TO_DEGREES);
+ mUpdateVisitor->setVisibility(actual_visibility);
+ bool hotspots = fgGetBool("/sim/panel-hotspots");
+ if (viewer) {
+ if (hotspots)
+ camera->setCullMask(camera->getCullMask()|SG_NODEMASK_PICK_BIT);
+ else
+ camera->setCullMask(camera->getCullMask()
+ & ~SG_NODEMASK_PICK_BIT);
+ } else {
+ if (hotspots)
+ sceneView->setCullMask(sceneView->getCullMask()
+ |SG_NODEMASK_PICK_BIT);
+ else
+ sceneView->setCullMask(sceneView->getCullMask()
+ &(~SG_NODEMASK_PICK_BIT));
+ sceneView->update();
+ sceneView->cull();
+ sceneView->draw();
}
- fgUpdate3DPanels();
-
- // We can do translucent menus, so why not. :-)
- menus->apply();
- glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ;
- puDisplay();
- // glDisable ( GL_BLEND ) ;
-
- glEnable( GL_DEPTH_TEST );
- glEnable( GL_FOG );
-
- // Fade out the splash screen over the first three seconds.
- double t = globals->get_sim_time_sec();
- if (t <= 2.5)
- fgSplashUpdate((2.5 - t) / 2.5);
}
} else {
view_h = height;
}
+ osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
+ if (viewer)
+ ;
+ // viewer->getCamera()->getViewport()->setViewport(0, height - view_h,
+// width, view_h);
+ else
+ sceneView->getViewport()->setViewport(0, height - view_h,
+ width, view_h);
+
+ static int lastwidth = 0;
+ static int lastheight = 0;
+ if (width != lastwidth)
+ fgSetInt("/sim/startup/xsize", lastwidth = width);
+ if (height != lastheight)
+ fgSetInt("/sim/startup/ysize", lastheight = height);
- glViewport( 0, (GLint)(height - view_h), (GLint)(width), (GLint)(view_h) );
-
- fgSetInt("/sim/startup/xsize", width);
- fgSetInt("/sim/startup/ysize", height);
guiInitMouse(width, height);
// for all views
setFOV( viewmgr->get_current_view()->get_h_fov(),
viewmgr->get_current_view()->get_v_fov() );
- // cout << "setFOV(" << viewmgr->get_current_view()->get_h_fov()
- // << ", " << viewmgr->get_current_view()->get_v_fov() << ")"
- // << endl;
-
}
-
- fgHUDReshape();
-
-}
-
-
-// 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");
-
- sgFrustum *f = ssgGetFrustum();
-
- // cout << " l = " << f->getLeft()
- // << " r = " << f->getRight()
- // << " b = " << f->getBot()
- // << " t = " << f->getTop()
- // << " n = " << f->getNear()
- // << " f = " << f->getFar()
- // << endl;
-
- double width = f->getRight() - f->getLeft();
- double height = f->getTop() - f->getBot();
-
- double l, r, t, b;
-
- if ( left_pct != NULL ) {
- l = f->getLeft() + width * left_pct->getDoubleValue();
- } else {
- l = f->getLeft();
- }
-
- if ( right_pct != NULL ) {
- r = f->getLeft() + width * right_pct->getDoubleValue();
- } else {
- r = f->getRight();
- }
-
- if ( bottom_pct != NULL ) {
- b = f->getBot() + height * bottom_pct->getDoubleValue();
- } else {
- b = f->getBot();
- }
-
- if ( top_pct != NULL ) {
- t = f->getBot() + height * top_pct->getDoubleValue();
- } else {
- t = f->getTop();
- }
-
- ssgSetFrustum(l, r, b, t, f->getNear(), f->getFar());
}
void FGRenderer::setFOV( float w, float h ) {
fov_width = w;
fov_height = h;
-
- // fully specify the view frustum before hacking it (so we don't
- // accumulate hacked effects
- ssgSetFOV( w, h );
- ssgSetNearFar( fov_near, fov_far );
- fgHackFrustum();
- sgEnviro.setFOV( w, h );
+ osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
+ if (viewer)
+ viewer->getCamera()->setProjectionMatrixAsPerspective(fov_height, 4.0/3.0, fov_near, fov_far);
+ else
+ sceneView->setProjectionMatrixAsPerspective(fov_height,
+ fov_width/fov_height,
+ fov_near, fov_far);
}
* 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;
+ osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
+ if (viewer)
+ viewer->getCamera()->setProjectionMatrixAsPerspective(fov_height, 4.0/3.0, fov_near, fov_far);
+ else
+ sceneView->setProjectionMatrixAsPerspective(fov_height,
+ fov_width/fov_height,
+ fov_near, fov_far);
- // fully specify the view frustum before hacking it (so we don't
- // accumulate hacked effects
- ssgSetNearFar( n, f );
- ssgSetFOV( fov_width, fov_height );
+}
- fgHackFrustum();
+bool
+FGRenderer::pick( unsigned x, unsigned y,
+ std::vector<SGSceneryPick>& pickList,
+ const osgGA::GUIEventAdapter* ea )
+{
+ osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
+ // wipe out the return ...
+ pickList.resize(0);
+
+ if (sceneView.valid()) {
+ osg::Node* sceneData = globals->get_scenery()->get_scene_graph();
+ if (!sceneData)
+ return false;
+
+ osg::Viewport* viewport = sceneView->getViewport();
+ if (!viewport)
+ return false;
+ // don't know why, but the update has partly happened somehow,
+ // so update the scenery part of the viewer
+ FGViewer *current_view = globals->get_current_view();
+ // Force update of center dependent values ...
+ current_view->set_dirty();
+ SGVec3d position = current_view->getViewPosition();
+ SGQuatd attitude = current_view->getViewOrientation();
+ SGVec3d osgPosition = attitude.transform(-position);
+ mCameraView->setPosition(osgPosition.osg());
+ mCameraView->setAttitude(inverse(attitude).osg());
+
+ osg::Matrix projection(sceneView->getProjectionMatrix());
+ osg::Matrix modelview(sceneView->getViewMatrix());
+
+ osg::NodePathList nodePath = sceneData->getParentalNodePaths();
+ // modify the view matrix so that it accounts for this nodePath's
+ // accumulated transform
+ if (!nodePath.empty())
+ modelview.preMult(computeLocalToWorld(nodePath.front()));
+
+ // swap the y values ...
+ y = viewport->height() - y;
+ // set up the pick visitor
+ osgUtil::PickVisitor pickVisitor(viewport, projection, modelview, x, y);
+ sceneData->accept(pickVisitor);
+ if (!pickVisitor.hits())
+ return false;
+
+ // collect all interaction callbacks on the pick ray.
+ // They get stored in the pickCallbacks list where they are sorted back
+ // to front and croasest to finest wrt the scenery node they are attached to
+ osgUtil::PickVisitor::LineSegmentHitListMap::const_iterator mi;
+ for (mi = pickVisitor.getSegHitList().begin();
+ mi != pickVisitor.getSegHitList().end();
+ ++mi) {
+ osgUtil::IntersectVisitor::HitList::const_iterator hi;
+ for (hi = mi->second.begin(); hi != mi->second.end(); ++hi) {
+ // ok, go back the nodes and ask for intersection callbacks,
+ // execute them in top down order
+ const osg::NodePath& np = hi->getNodePath();
+ osg::NodePath::const_reverse_iterator npi;
+ for (npi = np.rbegin(); npi != np.rend(); ++npi) {
+ SGSceneUserData* ud = SGSceneUserData::getSceneUserData(*npi);
+ if (!ud)
+ continue;
+ for (unsigned i = 0; i < ud->getNumPickCallbacks(); ++i) {
+ SGPickCallback* pickCallback = ud->getPickCallback(i);
+ if (!pickCallback)
+ continue;
+ SGSceneryPick sceneryPick;
+ /// note that this is done totally in doubles instead of
+ /// just using getWorldIntersectionPoint
+ osg::Vec3d localPt = hi->getLocalIntersectPoint();
+ sceneryPick.info.local = SGVec3d(localPt);
+ if (hi->getMatrix())
+ sceneryPick.info.wgs84 = SGVec3d(localPt*(*hi->getMatrix()));
+ else
+ sceneryPick.info.wgs84 = SGVec3d(localPt);
+ sceneryPick.callback = pickCallback;
+ pickList.push_back(sceneryPick);
+ }
+ }
+ }
+ }
+
+ return !pickList.empty();
+
+ } else if (viewer) {
+
+ // just compute intersections in the viewers method ...
+ typedef osgUtil::LineSegmentIntersector::Intersections Intersections;
+ Intersections intersections;
+ viewer->computeIntersections(ea->getX(), ea->getY(), intersections);
+
+ Intersections::iterator hit;
+ for (hit = intersections.begin(); hit != intersections.end(); ++hit) {
+ const osg::NodePath& np = hit->nodePath;
+ osg::NodePath::const_reverse_iterator npi;
+ for (npi = np.rbegin(); npi != np.rend(); ++npi) {
+ SGSceneUserData* ud = SGSceneUserData::getSceneUserData(*npi);
+ if (!ud)
+ continue;
+ for (unsigned i = 0; i < ud->getNumPickCallbacks(); ++i) {
+ SGPickCallback* pickCallback = ud->getPickCallback(i);
+ if (!pickCallback)
+ continue;
+ SGSceneryPick sceneryPick;
+ sceneryPick.info.local = SGVec3d(hit->getLocalIntersectPoint());
+ sceneryPick.info.wgs84 = SGVec3d(hit->getWorldIntersectPoint());
+ sceneryPick.callback = pickCallback;
+ pickList.push_back(sceneryPick);
+ }
+ }
+ }
+
+ return !pickList.empty();
+ } else { // we can get called early ...
+ return false;
+ }
}
+void
+FGRenderer::addCamera(osg::Camera* camera, bool useSceneData)
+{
+ mRealRoot->addChild(camera);
+}
+
+bool
+fgDumpSceneGraphToFile(const char* filename)
+{
+ return osgDB::writeNodeFile(*mRealRoot.get(), filename);
+}
// end of renderer.cxx
+