X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FMain%2Frenderer.cxx;h=32d7953380b417271fbedd5aead6ba626d1ae3df;hb=b587400846111cc4d6713dcdd38b715c97923d5a;hp=6eafe627fbce5305fa867133d0f5d2fdc9caf4c3;hpb=876bd2055c3900895205f73dd25869cc3598cafe;p=flightgear.git diff --git a/src/Main/renderer.cxx b/src/Main/renderer.cxx index 6eafe627f..32d795338 100644 --- a/src/Main/renderer.cxx +++ b/src/Main/renderer.cxx @@ -23,12 +23,12 @@ # include #endif -#include - #ifdef HAVE_WINDOWS_H # include #endif +#include + #include #include #include @@ -41,33 +41,33 @@ #include #include #include +#include +#include #include #include #include #include -#include +#include #include #include -#include -#include -#include #include #include #include -#include -#include #include #include #include #include #include +#include #include #include +#include #include #include +#include #include #include #include @@ -99,12 +99,13 @@ #include "splash.hxx" #include "renderer.hxx" #include "main.hxx" -#include "ViewPartitionNode.hxx" +#include "CameraGroup.hxx" +#include "FGEventHandler.hxx" +#include
-// XXX Make this go away when OSG 2.2 is released. -#if (FG_OSG_VERSION >= 21004) -#define UPDATE_VISITOR_IN_VIEWER 1 -#endif +using namespace osg; +using namespace simgear; +using namespace flightgear; class FGHintUpdateCallback : public osg::StateAttribute::Callback { public: @@ -138,6 +139,7 @@ public: { // Dynamic stuff, do not store geometry setUseDisplayList(false); + setDataVariance(Object::DYNAMIC); osg::StateSet* stateSet = getOrCreateStateSet(); stateSet->setRenderBinDetails(1001, "RenderBin"); @@ -157,8 +159,6 @@ public: { drawImplementation(*renderInfo.getState()); } void drawImplementation(osg::State& state) const { - if (!fgOSIsMainContext(state.getGraphicsContext())) - return; state.setActiveTextureUnit(0); state.setClientActiveTextureUnit(0); @@ -185,6 +185,7 @@ public: { // Dynamic stuff, do not store geometry setUseDisplayList(false); + setDataVariance(Object::DYNAMIC); osg::StateSet* stateSet = getOrCreateStateSet(); stateSet->setRenderBinDetails(1000, "RenderBin"); @@ -202,8 +203,6 @@ public: { drawImplementation(*renderInfo.getState()); } void drawImplementation(osg::State& state) const { - if (!fgOSIsMainContext(state.getGraphicsContext())) - return; state.setActiveTextureUnit(0); state.setClientActiveTextureUnit(0); state.disableAllVertexArrays(); @@ -237,6 +236,18 @@ private: 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(node)); @@ -244,21 +255,22 @@ public: osg::Light* light = lightSource->getLight(); FGLight *l = static_cast(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 { @@ -298,7 +310,7 @@ public: #if 0 FGLight *l = static_cast(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 @@ -341,7 +353,7 @@ public: SGUpdateVisitor* updateVisitor = static_cast(nv); osg::Fog* fog = static_cast(sa); fog->setMode(osg::Fog::EXP2); - fog->setColor(updateVisitor->getFogColor().osg()); + fog->setColor(toOsg(updateVisitor->getFogColor())); fog->setDensity(updateVisitor->getFogExp2Density()); } }; @@ -373,14 +385,12 @@ static osg::ref_ptr mRealRoot = new osg::Group; static osg::ref_ptr mRoot = new osg::Group; -static osg::ref_ptr viewPartition = new ViewPartitionNode; - FGRenderer::FGRenderer() { #ifdef FG_JPEG_SERVER jpgRenderFrame = FGRenderer::update; #endif - manipulator = new FGManipulator; + eventHandler = new FGEventHandler; } FGRenderer::~FGRenderer() @@ -402,44 +412,7 @@ FGRenderer::splashinit( void ) { // Scene doesn't seem to pass the frame stamp to the update // visitor automatically. mUpdateVisitor->setFrameStamp(mFrameStamp.get()); -#ifdef UPDATE_VISITOR_IN_VIEWER viewer->setUpdateVisitor(mUpdateVisitor.get()); -#else - osgViewer::Scene* scene = viewer->getScene(); - scene->setUpdateVisitor(mUpdateVisitor.get()); -#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 @@ -507,22 +480,43 @@ FGRenderer::init( void ) //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); - - lightSource->addChild(sceneGroup); - lightSource->addChild(thesky->getPreRoot()); - mRoot->addChild(lightSource); - + 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); @@ -545,21 +539,26 @@ FGRenderer::init( void ) stateSet->setUpdateCallback(new FGFogEnableUpdateCallback); // plug in the GUI - 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); - guiCamera->addChild(geode); - + 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(mRoot.get()); - viewPartition->addChild(sw); - viewPartition->addChild(thesky->getCloudRoot()); - - mRealRoot->addChild(viewPartition.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()); + // 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); } @@ -591,9 +590,6 @@ FGRenderer::update( bool refresh_camera_settings ) { 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(globals->get_subsystem("lighting")); // update fog params @@ -616,14 +612,6 @@ FGRenderer::update( bool refresh_camera_settings ) { // 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); - - FGManipulator *manipulator = globals->get_renderer()->getManipulator(); - manipulator->setPosition(position.osg()); - manipulator->setAttitude(attitude.osg()); } osg::Camera *camera = viewer->getCamera(); @@ -631,11 +619,11 @@ FGRenderer::update( bool refresh_camera_settings ) { if ( fgGetBool("/sim/rendering/textures") ) { SGVec4f clearColor(l->adj_fog_color()); - camera->setClearColor(clearColor.osg()); + camera->setClearColor(toOsg(clearColor)); } } else { SGVec4f clearColor(l->sky_color()); - camera->setClearColor(clearColor.osg()); + camera->setClearColor(toOsg(clearColor)); } // update fog params if visibility has changed @@ -657,64 +645,38 @@ FGRenderer::update( bool refresh_camera_settings ) { 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, @@ -747,25 +709,6 @@ FGRenderer::update( bool refresh_camera_settings ) { } // sgEnviro.setLight(l->adj_fog_color()); - - 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; - } else { - scene_nearplane = groundlevel_nearplane->getDoubleValue(); - scene_farplane = 120000.0f; - } - 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(), // current__view->getLongitude_deg(), @@ -795,19 +738,14 @@ FGRenderer::update( bool refresh_camera_settings ) { 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 - & ~simgear::BACKGROUND_BIT); + osg::Node::NodeMask cullMask = ~simgear::LIGHTS_BITS & ~simgear::PICK_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); + CameraGroup::getDefault()->setCameraCullMasks(cullMask); } @@ -833,8 +771,6 @@ FGRenderer::resize( int width, int height ) { if (height != lastheight) fgSetInt("/sim/startup/ysize", lastheight = height); - guiInitMouse(width, height); - // for all views FGViewMgr *viewmgr = globals->get_viewmgr(); if (viewmgr) { @@ -845,55 +781,52 @@ FGRenderer::resize( int width, int height ) { } } -void FGRenderer::setCameraParameters(float vfov, float aspectRatio, - float zNear, float zFar) -{ - zNear = .1; - osgViewer::Viewer* viewer = globals->get_renderer()->getViewer(); - viewer->getCamera()->setProjectionMatrixAsPerspective(vfov, - 1.0f / aspectRatio, - zNear, zFar); - -} bool -FGRenderer::pick( unsigned x, unsigned y, - std::vector& pickList, - const osgGA::GUIEventAdapter* ea ) +FGRenderer::pick(std::vector& pickList, + const osgGA::GUIEventAdapter* ea) { - osgViewer::Viewer* viewer = globals->get_renderer()->getViewer(); - // wipe out the return ... - pickList.resize(0); - - if (viewer) { - // just compute intersections in the viewers method ... + // wipe out the return ... + pickList.clear(); 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); + + 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); + } } - } } return !pickList.empty(); - } else { // we can get called early ... - return false; - } +} + +void +FGRenderer::setViewer(osgViewer::Viewer* viewer_) +{ + viewer = viewer_; +} + +void +FGRenderer::setEventHandler(FGEventHandler* eventHandler_) +{ + eventHandler = eventHandler_; } void