X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FMain%2Frenderer.cxx;h=32d7953380b417271fbedd5aead6ba626d1ae3df;hb=b7eb3bd0e128d39101dfa5846de991681aa5456f;hp=c3aeb4bfb8ebf00e736b713722a5cef4096cd395;hpb=e9c0c01ebba0c885f9bce0a3dec2d810fec134d2;p=flightgear.git diff --git a/src/Main/renderer.cxx b/src/Main/renderer.cxx index c3aeb4bfb..32d795338 100644 --- a/src/Main/renderer.cxx +++ b/src/Main/renderer.cxx @@ -47,6 +47,7 @@ #include #include #include +#include #include #include @@ -63,8 +64,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -98,6 +101,7 @@ #include "main.hxx" #include "CameraGroup.hxx" #include "FGEventHandler.hxx" +#include
using namespace osg; using namespace simgear; @@ -135,6 +139,7 @@ public: { // Dynamic stuff, do not store geometry setUseDisplayList(false); + setDataVariance(Object::DYNAMIC); osg::StateSet* stateSet = getOrCreateStateSet(); stateSet->setRenderBinDetails(1001, "RenderBin"); @@ -180,6 +185,7 @@ public: { // Dynamic stuff, do not store geometry setUseDisplayList(false); + setDataVariance(Object::DYNAMIC); osg::StateSet* stateSet = getOrCreateStateSet(); stateSet->setRenderBinDetails(1000, "RenderBin"); @@ -230,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)); @@ -237,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 { @@ -291,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 @@ -334,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()); } }; @@ -464,16 +483,39 @@ FGRenderer::init( void ) 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_ALPHA_TEST, osg::StateAttribute::ON); stateSet->setMode(GL_LIGHTING, osg::StateAttribute::ON); @@ -508,8 +550,15 @@ FGRenderer::init( void ) sw->setUpdateCallback(new FGScenerySwitchCallback); 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()); + // 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); } @@ -541,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 @@ -573,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 @@ -612,42 +658,16 @@ FGRenderer::update( bool refresh_camera_settings ) { } SGSkyState sstate; - - SGVec3d viewPos = current__view->getViewPosition(); - sstate.view_pos = toVec3f(viewPos); - SGGeod geodViewPos = SGGeod::fromCart(viewPos); - SGGeod geodZeroViewPos = SGGeod::fromGeodM(geodViewPos, 0); - sstate.zero_elev = toVec3f(SGVec3d::fromGeod(geodZeroViewPos)); - SGQuatd hlOr = SGQuatd::fromLonLat(geodViewPos); - sstate.view_up = toVec3f(hlOr.backTransform(-SGVec3d::e3())); - sstate.lon = geodViewPos.getLongitudeRad(); - sstate.lat = geodViewPos.getLatitudeRad(); - sstate.alt = geodViewPos.getElevationM(); + sstate.pos = current__view->getViewPosition(); + sstate.pos_geod = current__view->getPosition(); + sstate.ori = current__view->getViewOrientation(); sstate.spin = l->get_sun_rotation(); sstate.gst = globals->get_time_params()->getGst(); sstate.sun_dist = 50000.0 * sun_horiz_eff; sstate.moon_dist = 40000.0 * moon_horiz_eff; sstate.sun_angle = l->get_sun_angle(); - - /* - 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 ); - */ - 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()); @@ -765,7 +785,6 @@ bool FGRenderer::pick(std::vector& pickList, const osgGA::GUIEventAdapter* ea) { - osgViewer::Viewer* viewer = globals->get_renderer()->getViewer(); // wipe out the return ... pickList.clear(); typedef osgUtil::LineSegmentIntersector::Intersections Intersections; @@ -788,8 +807,8 @@ FGRenderer::pick(std::vector& pickList, if (!pickCallback) continue; SGSceneryPick sceneryPick; - sceneryPick.info.local = SGVec3d(hit->getLocalIntersectPoint()); - sceneryPick.info.wgs84 = SGVec3d(hit->getWorldIntersectPoint()); + sceneryPick.info.local = toSG(hit->getLocalIntersectPoint()); + sceneryPick.info.wgs84 = toSG(hit->getWorldIntersectPoint()); sceneryPick.callback = pickCallback; pickList.push_back(sceneryPick); }