1
0
Fork 0

fix moon lighting at night

This hasn't worked since the OSG port was initially checked in. A real
phase-of-the-moon bug!
This commit is contained in:
Tim Moore 2009-10-30 11:32:58 +01:00
parent 3a890859d3
commit e0a779adb1
2 changed files with 58 additions and 17 deletions

View file

@ -147,6 +147,7 @@ void fgOSOpenWindow(bool stencil)
viewer->setSceneData(new osg::Group);
globals->get_renderer()->setViewer(viewer.get());
CameraGroup::setDefault(cameraGroup);
viewer->setLightingMode(View::NO_LIGHT);
}
static int status = 0;

View file

@ -66,6 +66,7 @@
#include <simgear/scene/util/SGSceneUserData.hxx>
#include <simgear/scene/tgdb/GroundLightManager.hxx>
#include <simgear/scene/tgdb/pt_lights.hxx>
#include <simgear/structure/OSGUtils.hxx>
#include <simgear/props/props.hxx>
#include <simgear/timing/sg_time.hxx>
#include <simgear/ephemeris/ephemeris.hxx>
@ -232,6 +233,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<osg::LightSource*>(node));
@ -239,21 +252,22 @@ public:
osg::Light* light = lightSource->getLight();
FGLight *l = static_cast<FGLight*>(globals->get_subsystem("lighting"));
light->setAmbient(toOsg(l->scene_ambient()));
light->setDiffuse(toOsg(l->scene_diffuse()));
light->setSpecular(toOsg(l->scene_specular()));
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);
osg::Vec3f direction(l->sun_vec()[0], l->sun_vec()[1], l->sun_vec()[2]);
light->setDirection(direction);
light->setSpotExponent(0);
light->setSpotCutoff(180);
light->setConstantAttenuation(1);
light->setLinearAttenuation(0);
light->setQuadraticAttenuation(0);
traverse(node, nv);
}
private:
const bool _isSun;
};
class FGWireFrameModeUpdateCallback : public osg::StateAttribute::Callback {
@ -466,16 +480,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);
@ -510,6 +547,9 @@ 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());
}