diff --git a/VisualStudio/Demos/osgshadowtexture/osgshadowtexture.dsp b/VisualStudio/Demos/osgshadowtexture/osgshadowtexture.dsp index 70f142a2d..ec1bb8d14 100644 --- a/VisualStudio/Demos/osgshadowtexture/osgshadowtexture.dsp +++ b/VisualStudio/Demos/osgshadowtexture/osgshadowtexture.dsp @@ -1,95 +1,112 @@ -# Microsoft Developer Studio Project File - Name="Demo osgprerender" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -CFG=Demo osgprerender - Win32 Release -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "osgprerender.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "osgprerender.mak" CFG="Demo osgprerender - Win32 Release" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "Demo osgprerender - Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "Demo osgprerender - Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "Demo osgprerender - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Release" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /MD /W3 /GR /GX /O2 /I "../../../include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD BASE RSC /l 0x809 /d "NDEBUG" -# ADD RSC /l 0x809 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 /nologo /subsystem:console /pdb:none /machine:I386 /out:"../../../bin/osgprerender.exe" /libpath:"../../../lib" - -!ELSEIF "$(CFG)" == "Demo osgprerender - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug" -# PROP Intermediate_Dir "Debug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /MDd /W3 /Gm /vd0 /GR /GX /Zi /Od /I "../../../include" /D "_CONSOLE" /D "_MBCS" /D "FL_DLL" /D "WIN32" /D "_DEBUG" /FR /YX /FD /c -# ADD BASE RSC /l 0x809 /d "_DEBUG" -# ADD RSC /l 0x809 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 glut32.lib glu32.lib opengl32.lib /nologo /subsystem:console /debug /machine:I386 /nodefaultlib:"libcmt" /out:"../../../bin/osgprerenderd.exe" /pdbtype:sept /libpath:"../../../lib" -# SUBTRACT LINK32 /incremental:no - -!ENDIF - -# Begin Target - -# Name "Demo osgprerender - Win32 Release" -# Name "Demo osgprerender - Win32 Debug" -# Begin Source File - -SOURCE=..\..\..\src\Demos\osgprerender\osgprerender.cpp -# End Source File -# End Target -# Begin Group "Resource Files" - -# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" -# End Group -# End Project +# Microsoft Developer Studio Project File - Name="Demo osgshadowtexture" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=Demo osgshadowtexture - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "osgshadowtexture.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "osgshadowtexture.mak" CFG="Demo osgshadowtexture - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "Demo osgshadowtexture - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "Demo osgshadowtexture - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "Demo osgshadowtexture - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GR /GX /O2 /I "../../../include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x809 /d "NDEBUG" +# ADD RSC /l 0x809 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 /nologo /subsystem:console /pdb:none /machine:I386 /out:"../../../bin/osgshadowtexture.exe" /libpath:"../../../lib" + +!ELSEIF "$(CFG)" == "Demo osgshadowtexture - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MDd /W3 /Gm /vd0 /GR /GX /Zi /Od /I "../../../include" /D "_CONSOLE" /D "_MBCS" /D "FL_DLL" /D "WIN32" /D "_DEBUG" /YX /FD /c +# SUBTRACT CPP /Fr +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /nodefaultlib:"libcmt" /out:"../../../bin/osgshadowtextured.exe" /pdbtype:sept /libpath:"../../../lib" +# SUBTRACT LINK32 /incremental:no + +!ENDIF + +# Begin Target + +# Name "Demo osgshadowtexture - Win32 Release" +# Name "Demo osgshadowtexture - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\Src\Demos\osgshadowtexture\osgshadowtexture.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Src\Demos\osgshadowtexture\CreateShadowedScene.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter ";h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\..\Src\Demos\osgshadowtexture\CreateShadowedScene.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "" +# End Group +# End Target +# End Project diff --git a/include/osg/Plane b/include/osg/Plane index 2316fee21..37f823a16 100644 --- a/include/osg/Plane +++ b/include/osg/Plane @@ -87,6 +87,13 @@ class SG_EXPORT Plane inline bool valid() const { return _fv.valid(); } + inline bool operator == (const Plane& plane) const { return _fv==plane._fv; } + inline bool operator != (const Plane& plane) const { return _fv!=plane._fv; } + inline bool operator < (const Plane& plane) const { return _fv +#include #include namespace osg { @@ -92,9 +92,11 @@ class SG_EXPORT TexGen : public StateAttribute S, T, R, Q }; - void setPlane(Coord which, const Vec4& plane); + void setPlane(Coord which, const Plane& plane); - const Vec4& getPlane(Coord which) const; + Plane& getPlane(Coord which); + + const Plane& getPlane(Coord which) const; protected : @@ -103,7 +105,7 @@ class SG_EXPORT TexGen : public StateAttribute Mode _mode; /// additional texgen coefficents for GL_OBJECT_PLANE or GL_EYE_PLANE, - Vec4 _plane_s, _plane_t, _plane_r, _plane_q; + Plane _plane_s, _plane_t, _plane_r, _plane_q; }; diff --git a/src/Demos/osgshadowtexture/CreateShadowedScene.cpp b/src/Demos/osgshadowtexture/CreateShadowedScene.cpp new file mode 100644 index 000000000..ba7b91df7 --- /dev/null +++ b/src/Demos/osgshadowtexture/CreateShadowedScene.cpp @@ -0,0 +1,274 @@ +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "CreateShadowedScene.h" + + + +class CreateShadowTextureCullCallback : public osg::NodeCallback +{ + public: + + CreateShadowTextureCullCallback(osg::Node* shadower,const osg::Vec3& position, const osg::Vec4& ambientLightColor, unsigned int textureUnit): + _shadower(shadower), + _position(position), + _ambientLightColor(ambientLightColor), + _unit(textureUnit) + { + _texture = new osg::Texture2D; + _texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR); + _texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR); + } + + virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) + { + + osgUtil::CullVisitor* cullVisitor = dynamic_cast(nv); + if (cullVisitor && (_texture.valid() && _shadower.valid())) + { + doPreRender(*node,*cullVisitor); + + } + else + { + // must traverse the shadower + traverse(node,nv); + } + } + + protected: + + void doPreRender(osg::Node& node, osgUtil::CullVisitor& cv); + + osg::ref_ptr _shadower; + osg::ref_ptr _texture; + osg::Vec3 _position; + osg::Vec4 _ambientLightColor; + unsigned int _unit; + + // we need this to get round the order dependance + // of eye linear tex gen... + class MyTexGen : public osg::TexGen + { + public: + + void setMatrix(const osg::Matrix& matrix) + { + _matrix = matrix; + } + + virtual void apply(osg::State& state) const + { + glPushMatrix(); + glLoadMatrixf(_matrix.ptr()); + TexGen::apply(state); + glPopMatrix(); + } + + osg::Matrix _matrix; + }; + +}; + +void CreateShadowTextureCullCallback::doPreRender(osg::Node& node, osgUtil::CullVisitor& cv) +{ + + const osg::BoundingSphere& bs = _shadower->getBound(); + if (!bs.valid()) + { + osg::notify(osg::WARN) << "bb invalid"<<_shadower.get()< rtts = osgNew osgUtil::RenderToTextureStage; + + // set up lighting. + // currently ignore lights in the scene graph itself.. + // will do later. + osgUtil::RenderStage* previous_stage = cv.getCurrentRenderBin()->_stage; + + // set up the background color and clear mask. + rtts->setClearColor(osg::Vec4(1.0f,1.0f,1.0f,0.0f)); + rtts->setClearMask(previous_stage->getClearMask()); + + // set up to charge the same RenderStageLighting is the parent previous stage. + rtts->setRenderStageLighting(previous_stage->getRenderStageLighting()); + + + // record the render bin, to be restored after creation + // of the render to text + osgUtil::RenderBin* previousRenderBin = cv.getCurrentRenderBin(); + + // set the current renderbin to be the newly created stage. + cv.setCurrentRenderBin(rtts.get()); + + + float centerDistance = (_position-bs.center()).length(); + + float znear = centerDistance+bs.radius(); + float zfar = centerDistance-bs.radius(); + float zNearRatio = 0.001f; + if (znearmakeFrustum(-right,right,-top,top,znear,zfar); + + cv.pushProjectionMatrix(projection); + + osg::Matrix* matrix = new osg::Matrix; + matrix->makeLookAt(_position,bs.center(),osg::Vec3(0.0f,1.0f,0.0f)); + + + osg::Matrix MV = cv.getModelViewMatrix(); + + // compute the matrix which takes a vertex from local coords into tex coords + // will use this later to specify osg::TexGen.. + osg::Matrix MVPT = + *matrix * + *projection * + osg::Matrix::translate(1.0,1.0,1.0) * + osg::Matrix::scale(0.5f,0.5f,0.5f); + + cv.pushModelViewMatrix(matrix); + + osg::ref_ptr shadowState = osgNew osg::StateSet; + + // make the material black for a shadow. + osg::Material* material = new osg::Material; + material->setAmbient(osg::Material::FRONT_AND_BACK,_ambientLightColor); + material->setDiffuse(osg::Material::FRONT_AND_BACK,osg::Vec4(0.0f,0.0f,0.0f,1.0f)); + material->setEmission(osg::Material::FRONT_AND_BACK,osg::Vec4(0.0f,0.0f,0.0f,1.0f)); + material->setShininess(osg::Material::FRONT_AND_BACK,0.0f); + shadowState->setAttribute(material,osg::StateAttribute::OVERRIDE); + + cv.pushStateSet(shadowState.get()); + + { + + // traverse the shadower + _shadower->accept(cv); + + } + + cv.popStateSet(); + + // restore the previous model view matrix. + cv.popModelViewMatrix(); + + + // restore the previous model view matrix. + cv.popProjectionMatrix(); + + // restore the previous renderbin. + cv.setCurrentRenderBin(previousRenderBin); + + if (rtts->_renderGraphList.size()==0 && rtts->_bins.size()==0) + { + // getting to this point means that all the shadower has been + // culled by small feature culling or is beyond LOD ranges. + return; + } + + + + int height = 256; + int width = 256; + + + const osg::Viewport& viewport = *cv.getViewport(); + + // offset the impostor viewport from the center of the main window + // viewport as often the edges of the viewport might be obscured by + // other windows, which can cause image/reading writing problems. + int center_x = viewport.x()+viewport.width()/2; + int center_y = viewport.y()+viewport.height()/2; + + osg::Viewport* new_viewport = new osg::Viewport; + new_viewport->setViewport(center_x-width/2,center_y-height/2,width,height); + rtts->setViewport(new_viewport); + + shadowState->setAttribute(new_viewport); + + // and the render to texture stage to the current stages + // dependancy list. + cv.getCurrentRenderBin()->_stage->addToDependencyList(rtts.get()); + + // if one exist attach texture to the RenderToTextureStage. + if (_texture.valid()) rtts->setTexture(_texture.get()); + + + // set up the stateset to decorate the shadower with the shadow texture + // with the appropriate tex gen coords. + osg::StateSet* stateset = new osg::StateSet; + + + MyTexGen* texgen = new MyTexGen; + texgen->setMatrix(MV); + texgen->setMode(osg::TexGen::EYE_LINEAR); + texgen->setPlane(osg::TexGen::S,osg::Plane(MVPT(0,0),MVPT(1,0),MVPT(2,0),MVPT(3,0))); + texgen->setPlane(osg::TexGen::T,osg::Plane(MVPT(0,1),MVPT(1,1),MVPT(2,1),MVPT(3,1))); + texgen->setPlane(osg::TexGen::R,osg::Plane(MVPT(0,2),MVPT(1,2),MVPT(2,2),MVPT(3,2))); + texgen->setPlane(osg::TexGen::Q,osg::Plane(MVPT(0,3),MVPT(1,3),MVPT(2,3),MVPT(3,3))); + + stateset->setTextureAttributeAndModes(_unit,_texture.get(),osg::StateAttribute::ON); + stateset->setTextureAttribute(_unit,texgen); + stateset->setTextureMode(_unit,GL_TEXTURE_GEN_S,osg::StateAttribute::ON); + stateset->setTextureMode(_unit,GL_TEXTURE_GEN_T,osg::StateAttribute::ON); + stateset->setTextureMode(_unit,GL_TEXTURE_GEN_R,osg::StateAttribute::ON); + stateset->setTextureMode(_unit,GL_TEXTURE_GEN_Q,osg::StateAttribute::ON); + + cv.pushStateSet(stateset); + + // must traverse the shadower + traverse(&node,&cv); + + cv.popStateSet(); + +} + + +// set up a light source with the shadower and shodower subgraphs below it +// with the appropriate callbacks set up. +osg::Group* createShadowedScene(osg::Node* shadower,osg::Node* shadowed,const osg::Vec3& lightPosition,float radius,unsigned int textureUnit=1) +{ + osg::LightSource* lightgroup = new osg::LightSource; + + osg::Light* light = new osg::Light; + light->setPosition(osg::Vec4(lightPosition,1.0f)); + light->setLightNum(0); + + lightgroup->setLight(light); + + osg::Vec4 ambientLightColor(0.1f,0.1f,0.1f,1.0f); + + // add the shadower + lightgroup->addChild(shadower); + + // add the shadowed with the callback to generate the shadow texture. + shadowed->setCullCallback(new CreateShadowTextureCullCallback(shadower,lightPosition,ambientLightColor,textureUnit)); + lightgroup->addChild(shadowed); + + osg::Geode* lightgeode = new osg::Geode; + lightgeode->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF); + lightgeode->addDrawable(new osg::ShapeDrawable(new osg::Sphere(lightPosition,radius))); + + lightgroup->addChild(lightgeode); + + return lightgroup; +} + diff --git a/src/Demos/osgshadowtexture/CreateShadowedScene.h b/src/Demos/osgshadowtexture/CreateShadowedScene.h new file mode 100644 index 000000000..870deba40 --- /dev/null +++ b/src/Demos/osgshadowtexture/CreateShadowedScene.h @@ -0,0 +1,12 @@ +#ifndef CREATESHADOWEDSCENE_H +#define CREATESHADOWEDSCENE_H + +#include +#include + +// function to create a lightsource which contain a shadower and showed subgraph, +// the showadowed subgrph has a cull callback to fire off a pre render to texture +// of the shadowed subgraph. +extern osg::Group* createShadowedScene(osg::Node* shadower,osg::Node* shadowed,const osg::Vec3& lightPosition,float radius,unsigned int textureUnit=1); + +#endif diff --git a/src/Demos/osgshadowtexture/Makefile b/src/Demos/osgshadowtexture/Makefile index 28d711c63..a064dde96 100644 --- a/src/Demos/osgshadowtexture/Makefile +++ b/src/Demos/osgshadowtexture/Makefile @@ -2,6 +2,7 @@ TOPDIR = ../../.. include $(TOPDIR)/Make/makedefs CXXFILES =\ + CreateShadowedScene.cpp\ osgshadowtexture.cpp\ LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS) diff --git a/src/Demos/osgshadowtexture/Makefile.inst b/src/Demos/osgshadowtexture/Makefile.inst index c781199fd..a77643de3 100644 --- a/src/Demos/osgshadowtexture/Makefile.inst +++ b/src/Demos/osgshadowtexture/Makefile.inst @@ -2,6 +2,7 @@ TOPDIR = ../.. include $(TOPDIR)/Make/makedefs CXXFILES =\ + CreateShadowedScene.cpp\ osgshadowtexture.cpp\ LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS) diff --git a/src/Demos/osgshadowtexture/osgshadowtexture.cpp b/src/Demos/osgshadowtexture/osgshadowtexture.cpp index 76f4177e4..a445e1a1d 100644 --- a/src/Demos/osgshadowtexture/osgshadowtexture.cpp +++ b/src/Demos/osgshadowtexture/osgshadowtexture.cpp @@ -4,12 +4,8 @@ #include #include #include -#include -#include -#include #include -#include #include #include @@ -23,245 +19,15 @@ #include +// include the call which creates the shadowed subgraph. +#include "CreateShadowedScene.h" + + // for the grid data.. #include "../osghangglide/terrain_coords.h" -class CreateShadowTextureCullCallback : public osg::NodeCallback -{ - public: - - CreateShadowTextureCullCallback(osg::Node* shadower,const osg::Vec3& position, const osg::Vec4& ambientLightColor, unsigned int textureUnit): - _shadower(shadower), - _position(position), - _ambientLightColor(ambientLightColor), - _unit(textureUnit) - { - _texture = new osg::Texture2D; - _texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR); - _texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR); - } - - virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) - { - - osgUtil::CullVisitor* cullVisitor = dynamic_cast(nv); - if (cullVisitor && (_texture.valid() && _shadower.valid())) - { - doPreRender(*node,*cullVisitor); - - } - else - { - // must traverse the shadower - traverse(node,nv); - } - } - - protected: - - void doPreRender(osg::Node& node, osgUtil::CullVisitor& cv); - - osg::ref_ptr _shadower; - osg::ref_ptr _texture; - osg::Vec3 _position; - osg::Vec4 _ambientLightColor; - unsigned int _unit; - - // we need this to get round the order dependance - // of eye linear tex gen... - class MyTexGen : public osg::TexGen - { - public: - - void setMatrix(const osg::Matrix& matrix) - { - _matrix = matrix; - } - - virtual void apply(osg::State& state) const - { - glPushMatrix(); - glLoadMatrixf(_matrix.ptr()); - TexGen::apply(state); - glPopMatrix(); - } - - osg::Matrix _matrix; - }; - -}; - -void CreateShadowTextureCullCallback::doPreRender(osg::Node& node, osgUtil::CullVisitor& cv) -{ - - const osg::BoundingSphere& bs = _shadower->getBound(); - if (!bs.valid()) - { - osg::notify(osg::WARN) << "bb invalid"<<_shadower.get()< rtts = osgNew osgUtil::RenderToTextureStage; - - // set up lighting. - // currently ignore lights in the scene graph itself.. - // will do later. - osgUtil::RenderStage* previous_stage = cv.getCurrentRenderBin()->_stage; - - // set up the background color and clear mask. - rtts->setClearColor(osg::Vec4(1.0f,1.0f,1.0f,0.0f)); - rtts->setClearMask(previous_stage->getClearMask()); - - // set up to charge the same RenderStageLighting is the parent previous stage. - rtts->setRenderStageLighting(previous_stage->getRenderStageLighting()); - - - // record the render bin, to be restored after creation - // of the render to text - osgUtil::RenderBin* previousRenderBin = cv.getCurrentRenderBin(); - - // set the current renderbin to be the newly created stage. - cv.setCurrentRenderBin(rtts.get()); - - - float centerDistance = (_position-bs.center()).length(); - - float znear = centerDistance+bs.radius(); - float zfar = centerDistance-bs.radius(); - float zNearRatio = 0.001f; - if (znearmakeFrustum(-right,right,-top,top,znear,zfar); - - cv.pushProjectionMatrix(projection); - - osg::Matrix* matrix = new osg::Matrix; - matrix->makeLookAt(_position,bs.center(),osg::Vec3(0.0f,1.0f,0.0f)); - - - osg::Matrix MV = cv.getModelViewMatrix(); - - // compute the matrix which takes a vertex from local coords into tex coords - // will use this later to specify osg::TexGen.. - osg::Matrix MVPT = - *matrix * - *projection * - osg::Matrix::translate(1.0,1.0,1.0) * - osg::Matrix::scale(0.5f,0.5f,0.5f); - - cv.pushModelViewMatrix(matrix); - - osg::ref_ptr shadowState = osgNew osg::StateSet; - - // make the material black for a shadow. - osg::Material* material = new osg::Material; - material->setAmbient(osg::Material::FRONT_AND_BACK,_ambientLightColor); - material->setDiffuse(osg::Material::FRONT_AND_BACK,osg::Vec4(0.0f,0.0f,0.0f,1.0f)); - material->setEmission(osg::Material::FRONT_AND_BACK,osg::Vec4(0.0f,0.0f,0.0f,1.0f)); - material->setShininess(osg::Material::FRONT_AND_BACK,0.0f); - shadowState->setAttribute(material,osg::StateAttribute::OVERRIDE); - - cv.pushStateSet(shadowState.get()); - - { - - // traverse the shadower - _shadower->accept(cv); - - } - - cv.popStateSet(); - - // restore the previous model view matrix. - cv.popModelViewMatrix(); - - - // restore the previous model view matrix. - cv.popProjectionMatrix(); - - // restore the previous renderbin. - cv.setCurrentRenderBin(previousRenderBin); - - if (rtts->_renderGraphList.size()==0 && rtts->_bins.size()==0) - { - // getting to this point means that all the shadower has been - // culled by small feature culling or is beyond LOD ranges. - return; - } - - - - int height = 256; - int width = 256; - - - const osg::Viewport& viewport = *cv.getViewport(); - - // offset the impostor viewport from the center of the main window - // viewport as often the edges of the viewport might be obscured by - // other windows, which can cause image/reading writing problems. - int center_x = viewport.x()+viewport.width()/2; - int center_y = viewport.y()+viewport.height()/2; - - osg::Viewport* new_viewport = new osg::Viewport; - new_viewport->setViewport(center_x-width/2,center_y-height/2,width,height); - rtts->setViewport(new_viewport); - - shadowState->setAttribute(new_viewport); - - // and the render to texture stage to the current stages - // dependancy list. - cv.getCurrentRenderBin()->_stage->addToDependencyList(rtts.get()); - - // if one exist attach texture to the RenderToTextureStage. - if (_texture.valid()) rtts->setTexture(_texture.get()); - - - // set up the stateset to decorate the shadower with the shadow texture - // with the appropriate tex gen coords. - osg::StateSet* stateset = new osg::StateSet; - - - MyTexGen* texgen = new MyTexGen; - texgen->setMatrix(MV); - texgen->setMode(osg::TexGen::EYE_LINEAR); - texgen->setPlane(osg::TexGen::S,osg::Plane(MVPT(0,0),MVPT(1,0),MVPT(2,0),MVPT(3,0))); - texgen->setPlane(osg::TexGen::T,osg::Plane(MVPT(0,1),MVPT(1,1),MVPT(2,1),MVPT(3,1))); - texgen->setPlane(osg::TexGen::R,osg::Plane(MVPT(0,2),MVPT(1,2),MVPT(2,2),MVPT(3,2))); - texgen->setPlane(osg::TexGen::Q,osg::Plane(MVPT(0,3),MVPT(1,3),MVPT(2,3),MVPT(3,3))); - - stateset->setTextureAttributeAndModes(_unit,_texture.get(),osg::StateAttribute::ON); - stateset->setTextureAttribute(_unit,texgen); - stateset->setTextureMode(_unit,GL_TEXTURE_GEN_S,osg::StateAttribute::ON); - stateset->setTextureMode(_unit,GL_TEXTURE_GEN_T,osg::StateAttribute::ON); - stateset->setTextureMode(_unit,GL_TEXTURE_GEN_R,osg::StateAttribute::ON); - stateset->setTextureMode(_unit,GL_TEXTURE_GEN_Q,osg::StateAttribute::ON); - - cv.pushStateSet(stateset); - - // must traverse the shadower - traverse(&node,&cv); - - cv.popStateSet(); - -} - - - - - - osg::AnimationPath* createAnimationPath(const osg::Vec3& center,float radius,double looptime) { // set up the animation path @@ -339,7 +105,6 @@ osg::Node* createBase(const osg::Vec3& center,float radius) grid->setHeight(c,r,(h+hieghtOffset)*hieghtScale); } } - geode->addDrawable(new osg::ShapeDrawable(grid)); @@ -357,27 +122,6 @@ osg::Node* createMovingModel(const osg::Vec3& center, float radius) osg::AnimationPath* animationPath = createAnimationPath(center,radius,animationLength); osg::Group* model = new osg::Group; - -// osg::Node* glider = osgDB::readNodeFile("glider.osg"); -// if (glider) -// { -// const osg::BoundingSphere& bs = glider->getBound(); -// -// float size = radius/bs.radius()*0.3f; -// osg::MatrixTransform* positioned = osgNew osg::MatrixTransform; -// positioned->setDataVariance(osg::Object::STATIC); -// positioned->setMatrix(osg::Matrix::translate(-bs.center())* -// osg::Matrix::scale(size,size,size)* -// osg::Matrix::rotate(osg::inDegrees(-90.0f),0.0f,0.0f,1.0f)); -// -// positioned->addChild(glider); -// -// osg::PositionAttitudeTransform* xform = osgNew osg::PositionAttitudeTransform; -// xform->setAppCallback(new osg::PositionAttitudeTransform::AnimationPathCallback(animationPath,0.0,1.0)); -// xform->addChild(positioned); -// -// model->addChild(xform); -// } osg::Node* cessna = osgDB::readNodeFile("cessna.osg"); if (cessna) @@ -404,35 +148,6 @@ osg::Node* createMovingModel(const osg::Vec3& center, float radius) } -// shadowed must be at least group right now as leaf nodes such as -// osg::Geode don't get traversed so their cull callbacks don't get called. -osg::Group* createShadowedScene(osg::Node* shadower,osg::Node* shadowed,const osg::Vec3& lightPosition,float radius,unsigned int textureUnit=1) -{ - osg::LightSource* lightgroup = new osg::LightSource; - - osg::Light* light = new osg::Light; - light->setPosition(osg::Vec4(lightPosition,1.0f)); - light->setLightNum(0); - - lightgroup->setLight(light); - - osg::Vec4 ambientLightColor(0.1f,0.1f,0.1f,1.0f); - - // add the shadower - lightgroup->addChild(shadower); - - // add the shadowed with the callback to generate the shadow texture. - shadowed->setCullCallback(new CreateShadowTextureCullCallback(shadower,lightPosition,ambientLightColor,textureUnit)); - lightgroup->addChild(shadowed); - - osg::Geode* lightgeode = new osg::Geode; - lightgeode->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF); - lightgeode->addDrawable(new osg::ShapeDrawable(new osg::Sphere(lightPosition,radius))); - - lightgroup->addChild(lightgeode); - - return lightgroup; -} osg::Node* createModel() @@ -484,17 +199,12 @@ int main( int argc, char **argv ) return 1; } - // tilt the scene so the default eye position is looking down on the model. - osg::MatrixTransform* rootnode = new osg::MatrixTransform; -// rootnode->setMatrix(osg::Matrix::rotate(osg::inDegrees(30.0f),1.0f,0.0f,0.0f)); - rootnode->addChild(model); - - // run optimization over the scene graph - osgUtil::Optimizer optimzer; + // comment out optimization over the scene graph right now as it optimizers away the shadow... will look into this.. + //osgUtil::Optimizer optimzer; //optimzer.optimize(rootnode); // add a viewport to the viewer and attach the scene graph. - viewer.addViewport( rootnode ); + viewer.addViewport( model ); // register trackball, flight and drive. viewer.registerCameraManipulator(new osgGA::TrackballManipulator); diff --git a/src/Demos/osgshape/osgshape.cpp b/src/Demos/osgshape/osgshape.cpp index c81309f3c..f5cc9ce5a 100644 --- a/src/Demos/osgshape/osgshape.cpp +++ b/src/Demos/osgshape/osgshape.cpp @@ -12,6 +12,7 @@ #include +// for the grid data.. #include "../osghangglide/terrain_coords.h" osg::Geode* createShapes() @@ -19,11 +20,10 @@ osg::Geode* createShapes() osg::Geode* geode = osgNew osg::Geode(); // --------------------------------------- - // Set up a StateSet to make the cube red + // Set up a StateSet to texture the objects // --------------------------------------- osg::StateSet* stateset = osgNew osg::StateSet(); - osg::Image* image = osgDB::readImageFile("Images/lz.rgb"); if (image) { diff --git a/src/Demos/osgtexture3D/osgtexture3D.cpp b/src/Demos/osgtexture3D/osgtexture3D.cpp index bcb39d635..509195abd 100644 --- a/src/Demos/osgtexture3D/osgtexture3D.cpp +++ b/src/Demos/osgtexture3D/osgtexture3D.cpp @@ -111,7 +111,7 @@ class ConstructStateCallback : public osg::NodeCallback osg::TexGen* texgen = dynamic_cast(attribute); if (texgen) { - texgen->setPlane(osg::TexGen::R, texgen->getPlane(osg::TexGen::R)+osg::Vec4(0.0f,0.0f,0.0f,0.001f)); + texgen->getPlane(osg::TexGen::R)[3] += 0.001f; } } diff --git a/src/osg/TexGen.cpp b/src/osg/TexGen.cpp index f27cddb2b..7fbfc9916 100644 --- a/src/osg/TexGen.cpp +++ b/src/osg/TexGen.cpp @@ -18,7 +18,7 @@ TexGen::~TexGen() } -void TexGen::setPlane(Coord which, const Vec4& plane) +void TexGen::setPlane(Coord which, const Plane& plane) { switch( which ) { @@ -30,8 +30,19 @@ void TexGen::setPlane(Coord which, const Vec4& plane) } } +const Plane& TexGen::getPlane(Coord which) const +{ + switch( which ) + { + case S : return _plane_s; + case T : return _plane_t; + case R : return _plane_r; + case Q : return _plane_q; + default : notify(WARN)<<"Error: invalid 'which' passed TexGen::getPlane(which)"<