diff --git a/include/osg/LightSource b/include/osg/LightSource index 14a1578e6..d303c4606 100644 --- a/include/osg/LightSource +++ b/include/osg/LightSource @@ -25,6 +25,26 @@ class SG_EXPORT LightSource : public Group META_Node(osg, LightSource); + enum ReferenceFrame + { + RELATIVE_TO_PARENTS, + RELATIVE_TO_ABSOLUTE + }; + + /** Set the light sources's ReferenceFrame, either to be relative to its + * parent reference frame, or relative to an absolute coordinate + * frame. RELATIVE_TO_PARENTS is the default. + * Note: setting the ReferenceFrame to be RELATIVE_TO_ABSOLUTE will + * also set the CullingActive flag on the light source, and hence all + * of its parents, to false, thereby disabling culling of it and + * all its parents. This is neccessary to prevent inappropriate + * culling, but may impact cull times if the absolute light source is + * deep in the scene graph. It is therefore recommend to only use + * absolute light source at the top of the scene. */ + void setReferenceFrame(ReferenceFrame rf); + + ReferenceFrame getReferenceFrame() const { return _referenceFrame; } + /** Set the attached light.*/ void setLight(StateAttribute* light); @@ -48,6 +68,8 @@ class SG_EXPORT LightSource : public Group StateAttribute::GLModeValue _value; ref_ptr _light; + + ReferenceFrame _referenceFrame; }; } diff --git a/include/osg/Transform b/include/osg/Transform index b37020fed..a0b3a4937 100644 --- a/include/osg/Transform +++ b/include/osg/Transform @@ -64,7 +64,7 @@ class SG_EXPORT Transform : public Group * culling, but may impact cull times if the absolute transform is * deep in the scene graph. It is therefore recommend to only use * absolute Transforms at the top of the scene, for such things as - * headlight LightSources or Heads up displays. */ + * heads up displays. */ void setReferenceFrame(ReferenceFrame rf); ReferenceFrame getReferenceFrame() const { return _referenceFrame; } diff --git a/src/Demos/osgproducer/osgproducer.cpp b/src/Demos/osgproducer/osgproducer.cpp index 3edd30308..c970090ca 100644 --- a/src/Demos/osgproducer/osgproducer.cpp +++ b/src/Demos/osgproducer/osgproducer.cpp @@ -124,12 +124,24 @@ int main( int argc, char **argv ) // set the globa state -// osg::StateSet* globalStateSet = new osg::StateSet; -// globalStateSet->setGlobalDefaults(); -// cg->setGlobalStateSet(globalStateSet); + osg::StateSet* globalStateSet = new osg::StateSet; + globalStateSet->setGlobalDefaults(); + cg->setGlobalStateSet(globalStateSet); + + + // add either a headlight or sun light to the scene. + osg::LightSource* lightsource = new osg::LightSource; + osg::Light* light = new osg::Light; + lightsource->setLight(light); + lightsource->setReferenceFrame(osg::LightSource::RELATIVE_TO_ABSOLUTE); + lightsource->setLocalStateSetModes(osg::StateAttribute::ON); + + lightsource->addChild(scene.get()); + // set the scene to render - cg->setSceneData(scene.get()); +// cg->setSceneData(scene.get()); + cg->setSceneData(lightsource); // set up the pthread stack size to large enough to run into problems. cg->setStackSize( 20*1024*1024); @@ -153,18 +165,24 @@ int main( int argc, char **argv ) cg->sync(); // set the frame stamp for the new frame. - double time_since_start = timer.delta_s(timer.tick(),start_tick); + double time_since_start = timer.delta_s(start_tick,timer.tick()); frameStamp->setFrameNumber(frameNumber); frameStamp->setReferenceTime(time_since_start); - + + // update the trackball tb.input( kbmcb.mx(), kbmcb.my(), kbmcb.mbutton() ); + // update the scene by traversing it with the the update visitor which will + // call all node update callbacks and animations. scene->accept(update); + // update the main camera cg->setView(tb.getMatrix().ptr()); - + + // fire off the cull and draw traversals of the scene. cg->frame(); + // increment the frame number ready for the next frame ++frameNumber; } return 0; diff --git a/src/osg/LightSource.cpp b/src/osg/LightSource.cpp index 4b686e441..4bf731aea 100644 --- a/src/osg/LightSource.cpp +++ b/src/osg/LightSource.cpp @@ -3,7 +3,8 @@ using namespace osg; LightSource::LightSource(): - _value(StateAttribute::ON) + _value(StateAttribute::ON), + _referenceFrame(RELATIVE_TO_PARENTS) { // switch off culling of light source nodes by default. setCullingActive(false); @@ -17,6 +18,11 @@ LightSource::~LightSource() // ref_ptr<> automactially decrements the reference count of attached lights. } +void LightSource::setReferenceFrame(ReferenceFrame rf) +{ + _referenceFrame = rf; + setCullingActive(_referenceFrame==RELATIVE_TO_PARENTS); +} void LightSource::setLight(StateAttribute* light) { @@ -44,7 +50,7 @@ bool LightSource::computeBound() const { Group::computeBound(); - if (_light.valid()) + if (_light.valid() && _referenceFrame==RELATIVE_TO_PARENTS) { const Light* light = dynamic_cast(_light.get()); if (light) diff --git a/src/osgPlugins/osg/LightSource.cpp b/src/osgPlugins/osg/LightSource.cpp index 6155db004..6b2958fa9 100644 --- a/src/osgPlugins/osg/LightSource.cpp +++ b/src/osgPlugins/osg/LightSource.cpp @@ -27,6 +27,19 @@ bool LightSource_readLocalData(Object& obj, Input& fr) LightSource& lightsource = static_cast(obj); + if (fr[0].matchWord("referenceFrame")) { + if (fr[1].matchWord("RELATIVE_TO_ABSOLUTE")) { + lightsource.setReferenceFrame(LightSource::RELATIVE_TO_ABSOLUTE); + fr += 2; + iteratorAdvanced = true; + } + if (fr[1].matchWord("RELATIVE_TO_PARENTS")) { + lightsource.setReferenceFrame(LightSource::RELATIVE_TO_PARENTS); + fr += 2; + iteratorAdvanced = true; + } + } + StateAttribute* light=fr.readStateAttribute(); if (light) { @@ -42,6 +55,16 @@ bool LightSource_writeLocalData(const Object& obj, Output& fw) { const LightSource& lightsource = static_cast(obj); + fw.indent() << "referenceFrame "; + switch (lightsource.getReferenceFrame()) { + case LightSource::RELATIVE_TO_ABSOLUTE: + fw << "RELATIVE_TO_ABSOLUTE\n"; + break; + case LightSource::RELATIVE_TO_PARENTS: + default: + fw << "RELATIVE_TO_PARENTS\n"; + }; + if (lightsource.getLight()) fw.writeObject(*lightsource.getLight()); return true; diff --git a/src/osgPlugins/osg/ShapeDrawable.cpp b/src/osgPlugins/osg/ShapeDrawable.cpp index 02b2dd2d8..a4fbe4c6f 100644 --- a/src/osgPlugins/osg/ShapeDrawable.cpp +++ b/src/osgPlugins/osg/ShapeDrawable.cpp @@ -17,25 +17,35 @@ RegisterDotOsgWrapperProxy g_ShapeDrawableFuncProxy new osg::ShapeDrawable, "ShapeDrawable", "Object Drawable ShapeDrawable", - &ShapeDrawable_readLocalData, - &ShapeDrawable_writeLocalData, + 0, + 0, DotOsgWrapper::READ_AND_WRITE ); -bool ShapeDrawable_readLocalData(Object& obj, Input& fr) -{ - bool iteratorAdvanced = false; - - ShapeDrawable& geom = static_cast(obj); - - bool matchedFirst = false; - - return iteratorAdvanced; -} - -bool ShapeDrawable_writeLocalData(const Object& obj, Output& fw) -{ - const ShapeDrawable& geom = static_cast(obj); - - return true; -} +// RegisterDotOsgWrapperProxy g_ShapeDrawableFuncProxy +// ( +// new osg::ShapeDrawable, +// "ShapeDrawable", +// "Object Drawable ShapeDrawable", +// &ShapeDrawable_readLocalData, +// &ShapeDrawable_writeLocalData, +// DotOsgWrapper::READ_AND_WRITE +// ); +// +// bool ShapeDrawable_readLocalData(Object& obj, Input& fr) +// { +// bool iteratorAdvanced = false; +// +// ShapeDrawable& geom = static_cast(obj); +// +// bool matchedFirst = false; +// +// return iteratorAdvanced; +// } +// +// bool ShapeDrawable_writeLocalData(const Object& obj, Output& fw) +// { +// const ShapeDrawable& geom = static_cast(obj); +// +// return true; +// } diff --git a/src/osgUtil/CullVisitor.cpp b/src/osgUtil/CullVisitor.cpp index 08ecbd22b..060eaaa00 100644 --- a/src/osgUtil/CullVisitor.cpp +++ b/src/osgUtil/CullVisitor.cpp @@ -347,11 +347,19 @@ void CullVisitor::apply(LightSource& node) StateSet* node_state = node.getStateSet(); if (node_state) pushStateSet(node_state); - RefMatrix& matrix = getModelViewMatrix(); StateAttribute* light = node.getLight(); if (light) { - addPositionedAttribute(&matrix,light); + if (node.getReferenceFrame()==osg::LightSource::RELATIVE_TO_PARENTS) + { + RefMatrix& matrix = getModelViewMatrix(); + addPositionedAttribute(&matrix,light); + } + else + { + // relative to absolute. + addPositionedAttribute(0,light); + } } handle_cull_callbacks_and_traverse(node);