// 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>
#include <simgear/compiler.h>
-#ifdef HAVE_WINDOWS_H
-# include <windows.h>
-#endif
-
#include <osg/ref_ptr>
#include <osg/AlphaFunc>
#include <osg/BlendFunc>
#include <osg/Depth>
#include <osg/Fog>
#include <osg/Group>
+#include <osg/Hint>
#include <osg/Light>
#include <osg/LightModel>
#include <osg/LightSource>
#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/util/RenderConstants.hxx>
#include <simgear/environment/visual_enviro.hxx>
-#include <Scenery/tileentry.hxx>
#include <Time/light.hxx>
#include <Time/light.hxx>
#include <Aircraft/aircraft.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 "ViewPartitionNode.hxx"
// XXX Make this go away when OSG 2.2 is released.
#if (FG_OSG_VERSION >= 21004)
#define UPDATE_VISITOR_IN_VIEWER 1
#endif
+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:
SGPuDrawable()
{
if (!fgOSIsMainContext(state.getGraphicsContext()))
return;
-
- state.pushStateSet(getStateSet());
- state.apply();
state.setActiveTextureUnit(0);
state.setClientActiveTextureUnit(0);
+
state.disableAllVertexArrays();
glPushAttrib(GL_ALL_ATTRIB_BITS);
glPopClientAttrib();
glPopAttrib();
-
- state.popStateSet();
- state.dirtyAllModes();
- state.dirtyAllAttributes();
- state.dirtyAllVertexArrays();
}
virtual osg::Object* cloneType() const { return new SGPuDrawable; }
{ 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();
glPopClientAttrib();
glPopAttrib();
- state.popStateSet();
- state.dirtyAllModes();
- state.dirtyAllAttributes();
- state.dirtyAllVertexArrays();
}
virtual osg::Object* cloneType() const { return new SGHUDAndPanelDrawable; }
static osg::ref_ptr<osg::Group> mRoot = new osg::Group;
-static osg::ref_ptr<osg::Camera> mBackGroundCamera = new osg::Camera;
+static osg::ref_ptr<ViewPartitionNode> viewPartition = new ViewPartitionNode;
FGRenderer::FGRenderer()
{
#endif
}
+namespace
+{
+// Create a slave camera that will be used to render a fixed GUI-like
+// element.
+osg::Camera*
+makeSlaveCamera(osg::Camera::RenderOrder renderOrder, int orderNum)
+{
+ using namespace osg;
+ Camera* camera = new osg::Camera;
+ GraphicsContext *gc = fgOSGetMainContext();
+
+ camera->setRenderOrder(renderOrder, orderNum);
+ camera->setClearMask(0);
+ camera->setInheritanceMask(CullSettings::ALL_VARIABLES
+ & ~(CullSettings::COMPUTE_NEAR_FAR_MODE
+ | CullSettings::CULLING_MODE));
+ camera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
+ camera->setCullingMode(osg::CullSettings::NO_CULLING);
+ camera->setGraphicsContext(gc);
+ // Establish an initial viewport. This may be altered,
+ // particularly when drawing a 2d panel.
+ const GraphicsContext::Traits *traits = gc->getTraits();
+ camera->setViewport(new Viewport(0, 0, traits->width, traits->height));
+ camera->setProjectionResizePolicy(Camera::FIXED);
+ camera->setReferenceFrame(Transform::ABSOLUTE_RF);
+ camera->setAllowEventFocus(false);
+ globals->get_renderer()->getViewer()->addSlave(camera, false);
+ return camera;
+}
+
+}
+
void
-FGRenderer::init( void ) {
- // The viewer can call this before the graphics context is current
- // in the main thread; indeed, in a multithreaded setup it might
- // never be current in the main thread.
- fgMakeCurrent();
+FGRenderer::init( void )
+{
osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
osg::initNotifyLevel();
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);
-
viewer->getCamera()
->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
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);
// 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->addChild(thesky->getPreRoot());
+ mRoot->addChild(lightSource);
stateSet = globals->get_scenery()->get_scene_graph()->getOrCreateStateSet();
stateSet->setMode(GL_BLEND, osg::StateAttribute::ON);
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::Camera* guiCamera = makeSlaveCamera(osg::Camera::POST_RENDER, 100);
+ guiCamera->setName("GUI");
osg::Geode* geode = new osg::Geode;
geode->addDrawable(new SGPuDrawable);
geode->addDrawable(new SGHUDAndPanelDrawable);
osg::Switch* sw = new osg::Switch;
sw->setUpdateCallback(new FGScenerySwitchCallback);
sw->addChild(mRoot.get());
+ viewPartition->addChild(sw);
+ viewPartition->addChild(thesky->getCloudRoot());
- mRealRoot->addChild(sw);
+ mRealRoot->addChild(viewPartition.get());
mRealRoot->addChild(FGCreateRedoutNode());
- mRealRoot->addChild(guiCamera);
}
// 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;
+ // XXX Given that the own airplane model is part of the scene
+ // graph, should this business be ripped out? The near plane is
+ // ignored by setCameraParameters.
if ( agl > 10.0 ) {
scene_nearplane = 10.0f;
scene_farplane = 120000.0f;
scene_nearplane = groundlevel_nearplane->getDoubleValue();
scene_farplane = 120000.0f;
}
- setNearFar( scene_nearplane, scene_farplane );
+ setCameraParameters(current__view->get_v_fov(),
+ current__view->get_aspect_ratio(),
+ scene_nearplane, scene_farplane);
// sgEnviro.startOfFrame(current__view->get_view_pos(),
// current__view->get_world_up(),
// 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 )
l->adj_fog_color(),
l->get_sun_angle()*SGD_RADIANS_TO_DEGREES);
mUpdateVisitor->setVisibility(actual_visibility);
+ viewPartition->setVisibility(actual_visibility);
simgear::GroundLightManager::instance()->update(mUpdateVisitor.get());
bool hotspots = fgGetBool("/sim/panel-hotspots");
- osg::Node::NodeMask cullMask = ~simgear::LIGHTS_BITS & ~simgear::PICK_BIT;
+ osg::Node::NodeMask cullMask = (~simgear::LIGHTS_BITS & ~simgear::PICK_BIT
+ & ~simgear::BACKGROUND_BIT);
cullMask |= simgear::GroundLightManager::instance()
->getLightNodeMask(mUpdateVisitor.get());
if (hotspots)
cullMask |= simgear::PICK_BIT;
camera->setCullMask(cullMask);
+ // XXX
for (int i = 0; i < viewer->getNumSlaves(); ++i)
viewer->getSlave(i)._camera->setCullMask(cullMask);
}
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() );
}
}
-
-// 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;
- osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
- viewer->getCamera()->setProjectionMatrixAsPerspective(fov_height, 4.0/3.0,
- fov_near, fov_far);
-}
-
-
-/** 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;
+void FGRenderer::setCameraParameters(float vfov, float aspectRatio,
+ float zNear, float zFar)
+{
+ zNear = .1;
osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
- viewer->getCamera()->setProjectionMatrixAsPerspective(fov_height, 4.0/3.0,
- fov_near, fov_far);
+ viewer->getCamera()->setProjectionMatrixAsPerspective(vfov,
+ 1.0f / aspectRatio,
+ zNear, zFar);
+
}
-
bool
FGRenderer::pick( unsigned x, unsigned y,
std::vector<SGSceneryPick>& pickList,