Moved the shadow creation code into a seperate CreateShadowedScene header and source,

and exposed just the basic createShadowedScene function in the header.
This commit is contained in:
Robert Osfield
2002-11-21 15:35:51 +00:00
parent 3f97d6a44d
commit a545f3b48c
11 changed files with 436 additions and 401 deletions

View File

@@ -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
# 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

View File

@@ -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<plane._fv; }
inline float* ptr() { return _fv.ptr(); }
inline const float* ptr() const { return _fv.ptr(); }
inline Vec4& asVec4() { return _fv; }
inline const Vec4& asVec4() const { return _fv; }

View File

@@ -5,7 +5,7 @@
#ifndef OSG_TEXGEN
#define OSG_TEXGEN 1
#include <osg/Vec4>
#include <osg/Plane>
#include <osg/StateAttribute>
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;
};

View File

@@ -0,0 +1,274 @@
#include <osg/Texture2D>
#include <osg/TexGen>
#include <osg/Material>
#include <osg/LightSource>
#include <osg/Geode>
#include <osg/ShapeDrawable>
#include <osgUtil/CullVisitor>
#include <osgUtil/RenderToTextureStage>
#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<osgUtil::CullVisitor*>(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<osg::Node> _shadower;
osg::ref_ptr<osg::Texture2D> _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()<<std::endl;
return;
}
// create the render to texture stage.
osg::ref_ptr<osgUtil::RenderToTextureStage> 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 (znear<zfar*zNearRatio) znear = zfar*zNearRatio;
// 2:1 aspect ratio as per flag geomtry below.
float top = (bs.radius()/centerDistance)*znear;
float right = top;
// set up projection.
osg::Matrix* projection = osgNew osg::Matrix;
projection->makeFrustum(-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<osg::StateSet> 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;
}

View File

@@ -0,0 +1,12 @@
#ifndef CREATESHADOWEDSCENE_H
#define CREATESHADOWEDSCENE_H
#include <osg/Node>
#include <osg/Vec3>
// 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

View File

@@ -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)

View File

@@ -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)

View File

@@ -4,12 +4,8 @@
#include <osg/PositionAttitudeTransform>
#include <osg/Geometry>
#include <osg/Texture2D>
#include <osg/TexGen>
#include <osg/Material>
#include <osg/LightSource>
#include <osgUtil/Optimizer>
#include <osgUtil/RenderToTextureStage>
#include <osgDB/Registry>
#include <osgDB/ReadFile>
@@ -23,245 +19,15 @@
#include <osgGLUT/Viewer>
// 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<osgUtil::CullVisitor*>(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<osg::Node> _shadower;
osg::ref_ptr<osg::Texture2D> _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()<<std::endl;
return;
}
// create the render to texture stage.
osg::ref_ptr<osgUtil::RenderToTextureStage> 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 (znear<zfar*zNearRatio) znear = zfar*zNearRatio;
// 2:1 aspect ratio as per flag geomtry below.
float top = (bs.radius()/centerDistance)*znear;
float right = top;
// set up projection.
osg::Matrix* projection = osgNew osg::Matrix;
projection->makeFrustum(-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<osg::StateSet> 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);

View File

@@ -12,6 +12,7 @@
#include <osg/Math>
// 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)
{

View File

@@ -111,7 +111,7 @@ class ConstructStateCallback : public osg::NodeCallback
osg::TexGen* texgen = dynamic_cast<osg::TexGen*>(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;
}
}

View File

@@ -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)"<<std::endl; return _plane_r;
}
}
const Vec4& TexGen::getPlane(Coord which) const
Plane& TexGen::getPlane(Coord which)
{
switch( which )
{