Hi latest version,
(1) NVidea Cards, the setting of the Polygon offset seems to be not correct
on my ATI it's seems to be correct (looks nice)
please test and check for good values, i don't now a good value for
this
(2) GLSL shader has to be generated dynamic, if we change the number of
split planes
the version no longer need any IF in the GLSL shader, this makes the
good a little bit different form the suggestion in the paper PSSM
(3) try it out and test
pssm --help
enjoy and have a nice weekend, i will be not online till monday. if you have
some ideas, fixes etc please send me the new code. then i will be able to
test it
out. i hope for next osg release we will have a good and robust PSSM
implementation what would be greate.
the next version of PSSM would have project maps, at the moment it supports
just directional lights
/adegli
2007/9/14, Adrian Egli <[EMAIL PROTECTED]>:
>
> hi,
>
> i will post the first version of the PSSM for a sun as directional lights.
>
>
> Please help in test, debug, and optimisation, than we can integrate it
> into OSG core, i would like doing this as soon as possible.
>
> call in a console...
> PSSM --help
>
> example
> PSSM.exe dumptruck.osg --noUpdate --mapcount 3
> PSSM.exe dumptruck.osg --noUpdate --mapcount 3 --NO-DEBUG
>
>
> * we need a better GLSL shader ! My version isn't yet good enough (and
> robust)
>
> * i guess there is still a little bug, the near-far clipping plane for the
> each camera (shadow)
>
> * ...
>
> others
>
> thanks for help
>
>
> / adrian
>
> --
> ********************************************
> Adrian Egli
>
--
********************************************
Adrian Egli
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
*
* This application is open source and may be redistributed and/or modified
* freely and without restriction, both in commericial and non commericial applications,
* as long as this copyright notice is maintained.
*
* This application is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
//#define ADDITIONAL_BASE_PLANE 1
#define MOVING_LIGHT 1
const int ReceivesShadowTraversalMask = 0x1;
const int CastsShadowTraversalMask = 0x2;
const int MAX_SPLIT_TEXTURES = 3;
const int size_display_debug_texture = 100;
#include <osgDB/ReadFile>
#include <osgUtil/Optimizer>
#include <osg/CoordinateSystemNode>
#include <osg/Switch>
#include <osgText/Text>
#include <osg/MatrixTransform>
#include <osg/Projection>
#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>
#include <osgGA/TrackballManipulator>
#include <osgGA/FlightManipulator>
#include <osgGA/DriveManipulator>
#include <osgGA/KeySwitchMatrixManipulator>
#include <osgGA/StateSetManipulator>
#include <osgGA/AnimationPathManipulator>
#include <osgGA/TerrainManipulator>
#include <osg/ComputeBoundsVisitor>
#include <osg/ShapeDrawable>
#include <osg/Geometry>
#include <osgShadow/ShadowedScene>
#include "ShadowPSSM.h"
#include <iostream>
namespace ModelThree
{
osg::Group* createModel(osg::ArgumentParser& arguments)
{
osg::Group* scene = new osg::Group;
osg::ref_ptr<osg::Geode> geode_1 = new osg::Geode;
scene->addChild(geode_1.get());
osg::ref_ptr<osg::Geode> geode_2 = new osg::Geode;
osg::ref_ptr<osg::MatrixTransform> transform_2 = new osg::MatrixTransform;
transform_2->addChild(geode_2.get());
transform_2->setUpdateCallback(new osg::AnimationPathCallback(osg::Vec3(0, 0, 0), osg::Z_AXIS, osg::inDegrees(45.0f)));
scene->addChild(transform_2.get());
osg::ref_ptr<osg::Geode> geode_3 = new osg::Geode;
osg::ref_ptr<osg::MatrixTransform> transform_3 = new osg::MatrixTransform;
transform_3->addChild(geode_3.get());
transform_3->setUpdateCallback(new osg::AnimationPathCallback(osg::Vec3(0, 0, 0), osg::Z_AXIS, osg::inDegrees(-22.5f)));
scene->addChild(transform_3.get());
const float radius = 0.8f;
const float height = 1.0f;
osg::ref_ptr<osg::TessellationHints> hints = new osg::TessellationHints;
hints->setDetailRatio(2.0f);
osg::ref_ptr<osg::ShapeDrawable> shape;
shape = new osg::ShapeDrawable(new osg::Box(osg::Vec3(0.0f, 0.0f, -2.0f), 10, 10.0f, 0.1f), hints.get());
shape->setColor(osg::Vec4(0.5f, 0.5f, 0.7f, 1.0f));
geode_1->addDrawable(shape.get());
shape = new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(0.0f, 0.0f, 0.0f), radius * 2), hints.get());
shape->setColor(osg::Vec4(0.8f, 0.8f, 0.8f, 1.0f));
geode_1->addDrawable(shape.get());
shape = new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(-3.0f, 0.0f, 0.0f), radius), hints.get());
shape->setColor(osg::Vec4(0.6f, 0.8f, 0.8f, 1.0f));
geode_2->addDrawable(shape.get());
shape = new osg::ShapeDrawable(new osg::Box(osg::Vec3(3.0f, 0.0f, 0.0f), 2 * radius), hints.get());
shape->setColor(osg::Vec4(0.4f, 0.9f, 0.3f, 1.0f));
geode_2->addDrawable(shape.get());
shape = new osg::ShapeDrawable(new osg::Cone(osg::Vec3(0.0f, -3.0f, 0.0f), radius, height), hints.get());
shape->setColor(osg::Vec4(0.2f, 0.5f, 0.7f, 1.0f));
geode_2->addDrawable(shape.get());
shape = new osg::ShapeDrawable(new osg::Cylinder(osg::Vec3(0.0f, 3.0f, 0.0f), radius, height), hints.get());
shape->setColor(osg::Vec4(1.0f, 0.3f, 0.3f, 1.0f));
geode_2->addDrawable(shape.get());
shape = new osg::ShapeDrawable(new osg::Box(osg::Vec3(0.0f, 0.0f, 3.0f), 2.0f, 2.0f, 0.1f), hints.get());
shape->setColor(osg::Vec4(0.8f, 0.8f, 0.4f, 1.0f));
geode_3->addDrawable(shape.get());
// material
osg::ref_ptr<osg::Material> matirial = new osg::Material;
matirial->setColorMode(osg::Material::DIFFUSE);
matirial->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4(0, 0, 0, 1));
matirial->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4(1, 1, 1, 1));
matirial->setShininess(osg::Material::FRONT_AND_BACK, 64.0f);
scene->getOrCreateStateSet()->setAttributeAndModes(matirial.get(), osg::StateAttribute::ON);
bool withBaseTexture = true;
while(arguments.read("--with-base-texture")) { withBaseTexture = true; }
while(arguments.read("--no-base-texture")) { withBaseTexture = false; }
if (withBaseTexture)
{
scene->getOrCreateStateSet()->setTextureAttributeAndModes( 0, new osg::Texture2D(osgDB::readImageFile("Images/lz.rgb")), osg::StateAttribute::ON);
}
return scene;
}
}
osg::Node* createBase(const osg::Vec3& center,float radius)
{
osg::Geode* geode = new osg::Geode;
osg::HeightField* grid = new osg::HeightField;
grid->allocate(2,2);
grid->setOrigin(center+osg::Vec3(-radius*20.0,-radius*20.0,0.0));
grid->setXInterval(radius*40);
grid->setYInterval(radius*40);
grid->setHeight(0,0,0);
grid->setHeight(0,1,0);
grid->setHeight(1,0,0);
grid->setHeight(1,1,0);
geode->addDrawable(new osg::ShapeDrawable(grid));
osg::Group* group = new osg::Group;
group->addChild(geode);
return group;
}
int main(int argc, char** argv)
{
putenv("OSG_WINDOW=500 250 512 512");
putenv("OSG_THREADING=SingleThreaded");
// use an ArgumentParser object to manage the program arguments.
osg::ArgumentParser arguments(&argc,argv);
arguments.getApplicationUsage()->setApplicationName(arguments.getApplicationName());
arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the standard OpenSceneGraph example which loads and visualises 3d models.");
arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...");
arguments.getApplicationUsage()->addCommandLineOption("--image <filename>","Load an image and render it on a quad");
arguments.getApplicationUsage()->addCommandLineOption("--dem <filename>","Load an image/DEM and render it on a HeightField");
arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display command line parameters");
arguments.getApplicationUsage()->addCommandLineOption("--help-env","Display environmental variables available");
arguments.getApplicationUsage()->addCommandLineOption("--help-keys","Display keyboard & mouse bindings available");
arguments.getApplicationUsage()->addCommandLineOption("--help-all","Display all command line, env vars and keyboard & mouse bindings.");
arguments.getApplicationUsage()->addCommandLineOption("--SingleThreaded","Select SingleThreaded threading model for viewer.");
arguments.getApplicationUsage()->addCommandLineOption("--CullDrawThreadPerContext","Select CullDrawThreadPerContext threading model for viewer.");
arguments.getApplicationUsage()->addCommandLineOption("--DrawThreadPerContext","Select DrawThreadPerContext threading model for viewer.");
arguments.getApplicationUsage()->addCommandLineOption("--CullThreadPerCameraDrawThreadPerContext","Select CullThreadPerCameraDrawThreadPerContext threading model for viewer.");
arguments.getApplicationUsage()->addCommandLineOption("--NO-DEBUG","Switch off displaying the PSSM Textures");
arguments.getApplicationUsage()->addCommandLineOption("--positionalLight", "Use a positional light.");
arguments.getApplicationUsage()->addCommandLineOption("--directionalLight", "Use a direction light.");
arguments.getApplicationUsage()->addCommandLineOption("--noUpdate", "Disable the updating the of light source.");
arguments.getApplicationUsage()->addCommandLineOption("--mapcount", "number of shadow maps.");
// if user request help write it out to cout.
bool helpAll = arguments.read("--help-all");
unsigned int helpType = ((helpAll || arguments.read("-h") || arguments.read("--help"))? osg::ApplicationUsage::COMMAND_LINE_OPTION : 0 ) |
((helpAll || arguments.read("--help-env"))? osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE : 0 ) |
((helpAll || arguments.read("--help-keys"))? osg::ApplicationUsage::KEYBOARD_MOUSE_BINDING : 0 );
if (helpType)
{
arguments.getApplicationUsage()->write(std::cout, helpType);
return 1;
}
osgViewer::Viewer viewer(arguments);
bool createBackgroundContextForCompiling = false;
while (arguments.read("--bc")) { createBackgroundContextForCompiling = true; }
bool createBackgroundThreadsForCompiling = false;
while (arguments.read("--bt")) { createBackgroundContextForCompiling = true; createBackgroundThreadsForCompiling = true; }
int iMAX_SPLIT_TEXTURES = MAX_SPLIT_TEXTURES;
while (arguments.read("--mapcount", iMAX_SPLIT_TEXTURES));
bool postionalLight = true;
while (arguments.read("--positionalLight")) postionalLight = true;
while (arguments.read("--directionalLight")) postionalLight = false;
bool updateLightPosition = true;
while (arguments.read("--noUpdate")) updateLightPosition = false;
// set up the camera manipulators.
{
osg::ref_ptr<osgGA::KeySwitchMatrixManipulator> keyswitchManipulator = new osgGA::KeySwitchMatrixManipulator;
keyswitchManipulator->addMatrixManipulator( '1', "Trackball", new osgGA::TrackballManipulator() );
keyswitchManipulator->addMatrixManipulator( '2', "Flight", new osgGA::FlightManipulator() );
keyswitchManipulator->addMatrixManipulator( '3', "Drive", new osgGA::DriveManipulator() );
keyswitchManipulator->addMatrixManipulator( '4', "Terrain", new osgGA::TerrainManipulator() );
std::string pathfile;
char keyForAnimationPath = '5';
while (arguments.read("-p",pathfile))
{
osgGA::AnimationPathManipulator* apm = new osgGA::AnimationPathManipulator(pathfile);
if (apm || !apm->valid())
{
unsigned int num = keyswitchManipulator->getNumMatrixManipulators();
keyswitchManipulator->addMatrixManipulator( keyForAnimationPath, "Path", apm );
keyswitchManipulator->selectMatrixManipulator(num);
++keyForAnimationPath;
}
}
viewer.setCameraManipulator( keyswitchManipulator.get() );
}
// add the state manipulator
viewer.addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) );
// add the thread model handler
viewer.addEventHandler(new osgViewer::ThreadingHandler);
// add the window size toggle handler
viewer.addEventHandler(new osgViewer::WindowSizeHandler);
// add the stats handler
viewer.addEventHandler(new osgViewer::StatsHandler);
// add the help handler
viewer.addEventHandler(new osgViewer::HelpHandler(arguments.getApplicationUsage()));
// add the record camera path handler
viewer.addEventHandler(new osgViewer::RecordCameraPathHandler);
// prepare shadow
osg::Group* veryRootGroup = new osg::Group;
bool non_debug=false;
osg::Geode* geoHolders[10];
while (arguments.read("--NO-DEBUG")) {non_debug=true; }
if ( ! non_debug ){
for ( int i = 0;i<iMAX_SPLIT_TEXTURES;i++ ){
osg::Geode* geode = new osg::Geode;
osg::Geometry* geom = osg::createTexturedQuadGeometry(osg::Vec3(2,2,0),osg::Vec3(196.0,0.0,0.0),osg::Vec3(0.0,196.0,0.0));
geom->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
geoHolders[i]=geode;
geode->addDrawable(geom);
osg::StateSet * stateset = geode->getOrCreateStateSet();
stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);
stateset->setRenderBinDetails(11, "RenderBin");
// create a camera to set up the projection and model view matrices, and the subgraph to drawn in the HUD
osg::Camera* camera = new osg::Camera;
// set the projection matrix
camera->setProjectionMatrix(osg::Matrix::ortho2D(0,200,0,200));
// set the view matrix
camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
camera->setViewMatrix(osg::Matrix::identity());
// only clear the depth buffer
camera->setClearMask(GL_COLOR_BUFFER_BIT);
switch(i)
{
case 0:
camera->setClearColor(osg::Vec4(1.0,0.5,0.5,1.0));
break;
case 1:
camera->setClearColor(osg::Vec4(0.5,1.0,0.5,1.0));
break;
case 2:
camera->setClearColor(osg::Vec4(0.5,0.5,1.0,1.0));
break;
default:
camera->setClearColor(osg::Vec4(1.0,1.0,1.0,1.0));
break;
}
// draw subgraph after main camera view.
camera->setRenderOrder(osg::Camera::POST_RENDER);
// we don't want the camera to grab event focus from the viewers main camera(s).
camera->setAllowEventFocus(false);
camera->setViewport(50,200+i*(size_display_debug_texture+2),size_display_debug_texture,size_display_debug_texture);
camera->addChild(geode);
veryRootGroup->addChild(camera);
}
}
osg::ref_ptr<osgShadow::ShadowedScene> shadowedScene = new osgShadow::ShadowedScene;
shadowedScene->setReceivesShadowTraversalMask(ReceivesShadowTraversalMask);
shadowedScene->setCastsShadowTraversalMask(CastsShadowTraversalMask);
osg::ref_ptr<osgShadow::ShadowPSSM> pssm;
if ( non_debug ) {
pssm = new osgShadow::ShadowPSSM(NULL,iMAX_SPLIT_TEXTURES);
} else {
pssm= new osgShadow::ShadowPSSM(geoHolders,iMAX_SPLIT_TEXTURES);
}
shadowedScene->setShadowTechnique(pssm.get());
// load the data
osg::ref_ptr<osg::Group> modelRoot = new osg::Group;
osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFiles(arguments);
if (!loadedModel.valid())
{
loadedModel = ModelThree::createModel(arguments);
}
osg::Vec3 center(0,0,0);//0.5*-loadedModel->getBound().radius());
center = center+loadedModel->getBound().center();
osg::Node* basePlane = createBase(center,loadedModel->getBound().radius());
modelRoot->addChild(loadedModel.get());
#ifdef ADDITIONAL_BASE_PLANE
modelRoot->addChild(basePlane);
#endif
// any option left unread are converted into errors to write out later.
arguments.reportRemainingOptionsAsUnrecognized();
// report any errors if they have occurred when parsing the program arguments.
if (arguments.errors())
{
arguments.writeErrorMessages(std::cout);
return 1;
}
// optimize the scene graph, remove redundant nodes and state etc.
osgUtil::Optimizer optimizer;
optimizer.optimize(modelRoot.get());
// get the bounds of the model.
osg::ComputeBoundsVisitor cbbv;
modelRoot->accept(cbbv);
osg::BoundingBox bb = cbbv.getBoundingBox();
osg::Vec4 lightpos;
if (postionalLight)
{
lightpos.set(bb.center().x(), bb.center().y(), bb.zMax() + bb.radius() ,1.0f);
}
else
{
lightpos.set(0.5f,0.25f,0.8f,0.0f);
}
osg::ref_ptr<osg::LightSource> ls = new osg::LightSource;
ls->getLight()->setPosition(lightpos);
if ( arguments.read("--coloured-light"))
{
ls->getLight()->setAmbient(osg::Vec4(1.0,0.0,0.0,1.0));
ls->getLight()->setDiffuse(osg::Vec4(0.0,1.0,0.0,1.0));
}
else
{
ls->getLight()->setAmbient(osg::Vec4(0.2,0.2,0.2,1.0));
ls->getLight()->setDiffuse(osg::Vec4(0.8,0.8,0.8,1.0));
}
shadowedScene->addChild(modelRoot.get());
shadowedScene->addChild(ls.get());
veryRootGroup->addChild(shadowedScene.get());
viewer.setSceneData( veryRootGroup );
viewer.realize();
if (createBackgroundContextForCompiling)
{
int numProcessors = OpenThreads::GetNumberOfProcessors();
int processNum = 0;
for(unsigned int i=0; i<= osg::GraphicsContext::getMaxContextID(); ++i)
{
osg::GraphicsContext* gc = osg::GraphicsContext::getOrCreateCompileContext(i);
if (gc && createBackgroundThreadsForCompiling)
{
gc->createGraphicsThread();
gc->getGraphicsThread()->setProcessorAffinity(processNum % numProcessors);
gc->getGraphicsThread()->startThread();
++processNum;
}
}
}
#ifdef MOVING_LIGHT
osg::Vec3d lightDir;
while (!viewer.done())
{
if (updateLightPosition)
{
float t = viewer.getFrameStamp()->getSimulationTime()*0.5;
if (postionalLight)
{
lightpos.set(bb.center().x()+sinf(t)*bb.radius(), bb.center().y() + cosf(t)*bb.radius(), bb.zMax() + bb.radius() ,1.0f);
}
else
{
lightpos.set(sinf(t),cosf(t),1.0f,0.0f);
}
ls->getLight()->setPosition(lightpos);
osg::Vec3 dir = bb.center()-osg::Vec3(lightpos.x(),lightpos.y(),lightpos.z());
dir.normalize();
ls->getLight()->setDirection(dir);
} else {
float t = 0.23f;
lightpos.set(bb.center().x()+sinf(t)*bb.radius(), bb.center().y() + cosf(t)*bb.radius(), bb.zMax() + bb.radius() ,1.0f);
ls->getLight()->setPosition(lightpos);
osg::Vec3 dir = bb.center()-osg::Vec3(lightpos.x(),lightpos.y(),lightpos.z());
dir.normalize();
ls->getLight()->setDirection(dir);
}
viewer.frame();
}
#else
viewer.run();
#endif
}
#ifndef OSGSHADOW_SHADOWPSSM
#define OSGSHADOW_SHADOWPSSM 1
#include <osg/Camera>
#include <osg/Material>
#include <osgShadow/ShadowTechnique>
namespace osgShadow {
class ShadowPSSM : public ShadowTechnique
{
public:
ShadowPSSM(osg::Geode** debugGroup=NULL, int icountplanes=3);
ShadowPSSM(const ShadowPSSM& es, const osg::CopyOp&
copyop=osg::CopyOp::SHALLOW_COPY);
META_Object(osgShadow, ShadowPSSM);
/** initialize the ShadowedScene and local cached data
structures.*/
virtual void init();
/** run the update traversal of the ShadowedScene and update
any loca chached data structures.*/
virtual void update(osg::NodeVisitor& nv);
/** run the cull traversal of the ShadowedScene and set up the
rendering for this ShadowTechnique.*/
virtual void cull(osgUtil::CullVisitor& cv);
/** Clean scene graph from any shadow technique specific nodes,
state and drawables.*/
virtual void cleanSceneGraph();
protected :
virtual ~ShadowPSSM() {}
struct PSSMShadowSplitTexture {
// RTT
osg::ref_ptr<osg::Camera> _camera;
osg::ref_ptr<osg::TexGen> _texgen;
osg::ref_ptr<osg::Texture2D> _texture;
osg::ref_ptr<osg::StateSet> _stateset;
unsigned int _textureUnit;
osg::Vec2d _ambientBias;
osg::ref_ptr<osg::Camera> _debug_camera;
osg::ref_ptr<osg::Texture2D> _debug_texture;
osg::ref_ptr<osg::StateSet> _debug_stateset;
unsigned int _debug_textureUnit;
// Light (SUN)
osg::Vec3d
_lightCameraSource;
osg::Vec3d
_lightCameraTarget;
osg::Vec3d
_lightDirection;
double
_lightNear;
double
_lightFar;
osg::Matrix
_cameraView;
osg::Matrix
_cameraProj;
unsigned int
_splitID;
unsigned int
_resolution;
osg::Uniform*
_farDistanceSplit;
};
typedef std::map<unsigned int,PSSMShadowSplitTexture>
PSSMShadowSplitTextureMap;
PSSMShadowSplitTextureMap _PSSMShadowSplitTextureMap;
private:
void calculateFrustumCorners(PSSMShadowSplitTexture
&pssmShadowSplitTexture,osg::Vec3d *frustumCorners);
void calculateLightInitalPosition(PSSMShadowSplitTexture
&pssmShadowSplitTexture,osg::Vec3d *frustumCorners);
void calculateLightNearFarFormFrustum(PSSMShadowSplitTexture
&pssmShadowSplitTexture,osg::Vec3d *frustumCorners);
void
calculateLightViewProjectionFormFrustum(PSSMShadowSplitTexture
&pssmShadowSplitTexture,osg::Vec3d *frustumCorners);
osg::Geode** _displayTexturesGroupingNode;
unsigned int _textureUnitOffset;
};
}
#endif
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
*
* This application is open source and may be redistributed and/or modified
* freely and without restriction, both in commericial and non commericial applications,
* as long as this copyright notice is maintained.
*
* This application is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
//#define ADDITIONAL_BASE_PLANE 1
#define MOVING_LIGHT 1
const int ReceivesShadowTraversalMask = 0x1;
const int CastsShadowTraversalMask = 0x2;
const int MAX_SPLIT_TEXTURES = 3;
const int size_display_debug_texture = 100;
#include <osgDB/ReadFile>
#include <osgUtil/Optimizer>
#include <osg/CoordinateSystemNode>
#include <osg/Switch>
#include <osgText/Text>
#include <osg/MatrixTransform>
#include <osg/Projection>
#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>
#include <osgGA/TrackballManipulator>
#include <osgGA/FlightManipulator>
#include <osgGA/DriveManipulator>
#include <osgGA/KeySwitchMatrixManipulator>
#include <osgGA/StateSetManipulator>
#include <osgGA/AnimationPathManipulator>
#include <osgGA/TerrainManipulator>
#include <osg/ComputeBoundsVisitor>
#include <osg/ShapeDrawable>
#include <osg/Geometry>
#include <osgShadow/ShadowedScene>
#include "ShadowPSSM.h"
#include <iostream>
namespace ModelThree
{
osg::Group* createModel(osg::ArgumentParser& arguments)
{
osg::Group* scene = new osg::Group;
osg::ref_ptr<osg::Geode> geode_1 = new osg::Geode;
scene->addChild(geode_1.get());
osg::ref_ptr<osg::Geode> geode_2 = new osg::Geode;
osg::ref_ptr<osg::MatrixTransform> transform_2 = new osg::MatrixTransform;
transform_2->addChild(geode_2.get());
transform_2->setUpdateCallback(new osg::AnimationPathCallback(osg::Vec3(0, 0, 0), osg::Z_AXIS, osg::inDegrees(45.0f)));
scene->addChild(transform_2.get());
osg::ref_ptr<osg::Geode> geode_3 = new osg::Geode;
osg::ref_ptr<osg::MatrixTransform> transform_3 = new osg::MatrixTransform;
transform_3->addChild(geode_3.get());
transform_3->setUpdateCallback(new osg::AnimationPathCallback(osg::Vec3(0, 0, 0), osg::Z_AXIS, osg::inDegrees(-22.5f)));
scene->addChild(transform_3.get());
const float radius = 0.8f;
const float height = 1.0f;
osg::ref_ptr<osg::TessellationHints> hints = new osg::TessellationHints;
hints->setDetailRatio(2.0f);
osg::ref_ptr<osg::ShapeDrawable> shape;
shape = new osg::ShapeDrawable(new osg::Box(osg::Vec3(0.0f, 0.0f, -2.0f), 10, 10.0f, 0.1f), hints.get());
shape->setColor(osg::Vec4(0.5f, 0.5f, 0.7f, 1.0f));
geode_1->addDrawable(shape.get());
shape = new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(0.0f, 0.0f, 0.0f), radius * 2), hints.get());
shape->setColor(osg::Vec4(0.8f, 0.8f, 0.8f, 1.0f));
geode_1->addDrawable(shape.get());
shape = new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(-3.0f, 0.0f, 0.0f), radius), hints.get());
shape->setColor(osg::Vec4(0.6f, 0.8f, 0.8f, 1.0f));
geode_2->addDrawable(shape.get());
shape = new osg::ShapeDrawable(new osg::Box(osg::Vec3(3.0f, 0.0f, 0.0f), 2 * radius), hints.get());
shape->setColor(osg::Vec4(0.4f, 0.9f, 0.3f, 1.0f));
geode_2->addDrawable(shape.get());
shape = new osg::ShapeDrawable(new osg::Cone(osg::Vec3(0.0f, -3.0f, 0.0f), radius, height), hints.get());
shape->setColor(osg::Vec4(0.2f, 0.5f, 0.7f, 1.0f));
geode_2->addDrawable(shape.get());
shape = new osg::ShapeDrawable(new osg::Cylinder(osg::Vec3(0.0f, 3.0f, 0.0f), radius, height), hints.get());
shape->setColor(osg::Vec4(1.0f, 0.3f, 0.3f, 1.0f));
geode_2->addDrawable(shape.get());
shape = new osg::ShapeDrawable(new osg::Box(osg::Vec3(0.0f, 0.0f, 3.0f), 2.0f, 2.0f, 0.1f), hints.get());
shape->setColor(osg::Vec4(0.8f, 0.8f, 0.4f, 1.0f));
geode_3->addDrawable(shape.get());
// material
osg::ref_ptr<osg::Material> matirial = new osg::Material;
matirial->setColorMode(osg::Material::DIFFUSE);
matirial->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4(0, 0, 0, 1));
matirial->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4(1, 1, 1, 1));
matirial->setShininess(osg::Material::FRONT_AND_BACK, 64.0f);
scene->getOrCreateStateSet()->setAttributeAndModes(matirial.get(), osg::StateAttribute::ON);
bool withBaseTexture = true;
while(arguments.read("--with-base-texture")) { withBaseTexture = true; }
while(arguments.read("--no-base-texture")) { withBaseTexture = false; }
if (withBaseTexture)
{
scene->getOrCreateStateSet()->setTextureAttributeAndModes( 0, new osg::Texture2D(osgDB::readImageFile("Images/lz.rgb")), osg::StateAttribute::ON);
}
return scene;
}
}
osg::Node* createBase(const osg::Vec3& center,float radius)
{
osg::Geode* geode = new osg::Geode;
osg::HeightField* grid = new osg::HeightField;
grid->allocate(2,2);
grid->setOrigin(center+osg::Vec3(-radius*20.0,-radius*20.0,0.0));
grid->setXInterval(radius*40);
grid->setYInterval(radius*40);
grid->setHeight(0,0,0);
grid->setHeight(0,1,0);
grid->setHeight(1,0,0);
grid->setHeight(1,1,0);
geode->addDrawable(new osg::ShapeDrawable(grid));
osg::Group* group = new osg::Group;
group->addChild(geode);
return group;
}
int main(int argc, char** argv)
{
putenv("OSG_WINDOW=500 250 512 512");
putenv("OSG_THREADING=SingleThreaded");
// use an ArgumentParser object to manage the program arguments.
osg::ArgumentParser arguments(&argc,argv);
arguments.getApplicationUsage()->setApplicationName(arguments.getApplicationName());
arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the standard OpenSceneGraph example which loads and visualises 3d models.");
arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...");
arguments.getApplicationUsage()->addCommandLineOption("--image <filename>","Load an image and render it on a quad");
arguments.getApplicationUsage()->addCommandLineOption("--dem <filename>","Load an image/DEM and render it on a HeightField");
arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display command line parameters");
arguments.getApplicationUsage()->addCommandLineOption("--help-env","Display environmental variables available");
arguments.getApplicationUsage()->addCommandLineOption("--help-keys","Display keyboard & mouse bindings available");
arguments.getApplicationUsage()->addCommandLineOption("--help-all","Display all command line, env vars and keyboard & mouse bindings.");
arguments.getApplicationUsage()->addCommandLineOption("--SingleThreaded","Select SingleThreaded threading model for viewer.");
arguments.getApplicationUsage()->addCommandLineOption("--CullDrawThreadPerContext","Select CullDrawThreadPerContext threading model for viewer.");
arguments.getApplicationUsage()->addCommandLineOption("--DrawThreadPerContext","Select DrawThreadPerContext threading model for viewer.");
arguments.getApplicationUsage()->addCommandLineOption("--CullThreadPerCameraDrawThreadPerContext","Select CullThreadPerCameraDrawThreadPerContext threading model for viewer.");
arguments.getApplicationUsage()->addCommandLineOption("--NO-DEBUG","Switch off displaying the PSSM Textures");
arguments.getApplicationUsage()->addCommandLineOption("--positionalLight", "Use a positional light.");
arguments.getApplicationUsage()->addCommandLineOption("--directionalLight", "Use a direction light.");
arguments.getApplicationUsage()->addCommandLineOption("--noUpdate", "Disable the updating the of light source.");
arguments.getApplicationUsage()->addCommandLineOption("--mapcount", "number of shadow maps.");
// if user request help write it out to cout.
bool helpAll = arguments.read("--help-all");
unsigned int helpType = ((helpAll || arguments.read("-h") || arguments.read("--help"))? osg::ApplicationUsage::COMMAND_LINE_OPTION : 0 ) |
((helpAll || arguments.read("--help-env"))? osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE : 0 ) |
((helpAll || arguments.read("--help-keys"))? osg::ApplicationUsage::KEYBOARD_MOUSE_BINDING : 0 );
if (helpType)
{
arguments.getApplicationUsage()->write(std::cout, helpType);
return 1;
}
osgViewer::Viewer viewer(arguments);
bool createBackgroundContextForCompiling = false;
while (arguments.read("--bc")) { createBackgroundContextForCompiling = true; }
bool createBackgroundThreadsForCompiling = false;
while (arguments.read("--bt")) { createBackgroundContextForCompiling = true; createBackgroundThreadsForCompiling = true; }
int iMAX_SPLIT_TEXTURES = MAX_SPLIT_TEXTURES;
while (arguments.read("--mapcount", iMAX_SPLIT_TEXTURES));
bool postionalLight = true;
while (arguments.read("--positionalLight")) postionalLight = true;
while (arguments.read("--directionalLight")) postionalLight = false;
bool updateLightPosition = true;
while (arguments.read("--noUpdate")) updateLightPosition = false;
// set up the camera manipulators.
{
osg::ref_ptr<osgGA::KeySwitchMatrixManipulator> keyswitchManipulator = new osgGA::KeySwitchMatrixManipulator;
keyswitchManipulator->addMatrixManipulator( '1', "Trackball", new osgGA::TrackballManipulator() );
keyswitchManipulator->addMatrixManipulator( '2', "Flight", new osgGA::FlightManipulator() );
keyswitchManipulator->addMatrixManipulator( '3', "Drive", new osgGA::DriveManipulator() );
keyswitchManipulator->addMatrixManipulator( '4', "Terrain", new osgGA::TerrainManipulator() );
std::string pathfile;
char keyForAnimationPath = '5';
while (arguments.read("-p",pathfile))
{
osgGA::AnimationPathManipulator* apm = new osgGA::AnimationPathManipulator(pathfile);
if (apm || !apm->valid())
{
unsigned int num = keyswitchManipulator->getNumMatrixManipulators();
keyswitchManipulator->addMatrixManipulator( keyForAnimationPath, "Path", apm );
keyswitchManipulator->selectMatrixManipulator(num);
++keyForAnimationPath;
}
}
viewer.setCameraManipulator( keyswitchManipulator.get() );
}
// add the state manipulator
viewer.addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) );
// add the thread model handler
viewer.addEventHandler(new osgViewer::ThreadingHandler);
// add the window size toggle handler
viewer.addEventHandler(new osgViewer::WindowSizeHandler);
// add the stats handler
viewer.addEventHandler(new osgViewer::StatsHandler);
// add the help handler
viewer.addEventHandler(new osgViewer::HelpHandler(arguments.getApplicationUsage()));
// add the record camera path handler
viewer.addEventHandler(new osgViewer::RecordCameraPathHandler);
// prepare shadow
osg::Group* veryRootGroup = new osg::Group;
bool non_debug=false;
osg::Geode* geoHolders[10];
while (arguments.read("--NO-DEBUG")) {non_debug=true; }
if ( ! non_debug ){
for ( int i = 0;i<iMAX_SPLIT_TEXTURES;i++ ){
osg::Geode* geode = new osg::Geode;
osg::Geometry* geom = osg::createTexturedQuadGeometry(osg::Vec3(2,2,0),osg::Vec3(196.0,0.0,0.0),osg::Vec3(0.0,196.0,0.0));
geom->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
geoHolders[i]=geode;
geode->addDrawable(geom);
osg::StateSet * stateset = geode->getOrCreateStateSet();
stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);
stateset->setRenderBinDetails(11, "RenderBin");
// create a camera to set up the projection and model view matrices, and the subgraph to drawn in the HUD
osg::Camera* camera = new osg::Camera;
// set the projection matrix
camera->setProjectionMatrix(osg::Matrix::ortho2D(0,200,0,200));
// set the view matrix
camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
camera->setViewMatrix(osg::Matrix::identity());
// only clear the depth buffer
camera->setClearMask(GL_COLOR_BUFFER_BIT);
switch(i)
{
case 0:
camera->setClearColor(osg::Vec4(1.0,0.5,0.5,1.0));
break;
case 1:
camera->setClearColor(osg::Vec4(0.5,1.0,0.5,1.0));
break;
case 2:
camera->setClearColor(osg::Vec4(0.5,0.5,1.0,1.0));
break;
default:
camera->setClearColor(osg::Vec4(1.0,1.0,1.0,1.0));
break;
}
// draw subgraph after main camera view.
camera->setRenderOrder(osg::Camera::POST_RENDER);
// we don't want the camera to grab event focus from the viewers main camera(s).
camera->setAllowEventFocus(false);
camera->setViewport(50,200+i*(size_display_debug_texture+2),size_display_debug_texture,size_display_debug_texture);
camera->addChild(geode);
veryRootGroup->addChild(camera);
}
}
osg::ref_ptr<osgShadow::ShadowedScene> shadowedScene = new osgShadow::ShadowedScene;
shadowedScene->setReceivesShadowTraversalMask(ReceivesShadowTraversalMask);
shadowedScene->setCastsShadowTraversalMask(CastsShadowTraversalMask);
osg::ref_ptr<osgShadow::ShadowPSSM> pssm;
if ( non_debug ) {
pssm = new osgShadow::ShadowPSSM(NULL,iMAX_SPLIT_TEXTURES);
} else {
pssm= new osgShadow::ShadowPSSM(geoHolders,iMAX_SPLIT_TEXTURES);
}
shadowedScene->setShadowTechnique(pssm.get());
// load the data
osg::ref_ptr<osg::Group> modelRoot = new osg::Group;
osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFiles(arguments);
if (!loadedModel.valid())
{
loadedModel = ModelThree::createModel(arguments);
}
osg::Vec3 center(0,0,0);//0.5*-loadedModel->getBound().radius());
center = center+loadedModel->getBound().center();
osg::Node* basePlane = createBase(center,loadedModel->getBound().radius());
modelRoot->addChild(loadedModel.get());
#ifdef ADDITIONAL_BASE_PLANE
modelRoot->addChild(basePlane);
#endif
// any option left unread are converted into errors to write out later.
arguments.reportRemainingOptionsAsUnrecognized();
// report any errors if they have occurred when parsing the program arguments.
if (arguments.errors())
{
arguments.writeErrorMessages(std::cout);
return 1;
}
// optimize the scene graph, remove redundant nodes and state etc.
osgUtil::Optimizer optimizer;
optimizer.optimize(modelRoot.get());
// get the bounds of the model.
osg::ComputeBoundsVisitor cbbv;
modelRoot->accept(cbbv);
osg::BoundingBox bb = cbbv.getBoundingBox();
osg::Vec4 lightpos;
if (postionalLight)
{
lightpos.set(bb.center().x(), bb.center().y(), bb.zMax() + bb.radius() ,1.0f);
}
else
{
lightpos.set(0.5f,0.25f,0.8f,0.0f);
}
osg::ref_ptr<osg::LightSource> ls = new osg::LightSource;
ls->getLight()->setPosition(lightpos);
if ( arguments.read("--coloured-light"))
{
ls->getLight()->setAmbient(osg::Vec4(1.0,0.0,0.0,1.0));
ls->getLight()->setDiffuse(osg::Vec4(0.0,1.0,0.0,1.0));
}
else
{
ls->getLight()->setAmbient(osg::Vec4(0.2,0.2,0.2,1.0));
ls->getLight()->setDiffuse(osg::Vec4(0.8,0.8,0.8,1.0));
}
shadowedScene->addChild(modelRoot.get());
shadowedScene->addChild(ls.get());
veryRootGroup->addChild(shadowedScene.get());
viewer.setSceneData( veryRootGroup );
viewer.realize();
if (createBackgroundContextForCompiling)
{
int numProcessors = OpenThreads::GetNumberOfProcessors();
int processNum = 0;
for(unsigned int i=0; i<= osg::GraphicsContext::getMaxContextID(); ++i)
{
osg::GraphicsContext* gc = osg::GraphicsContext::getOrCreateCompileContext(i);
if (gc && createBackgroundThreadsForCompiling)
{
gc->createGraphicsThread();
gc->getGraphicsThread()->setProcessorAffinity(processNum % numProcessors);
gc->getGraphicsThread()->startThread();
++processNum;
}
}
}
#ifdef MOVING_LIGHT
osg::Vec3d lightDir;
while (!viewer.done())
{
if (updateLightPosition)
{
float t = viewer.getFrameStamp()->getSimulationTime()*0.5;
if (postionalLight)
{
lightpos.set(bb.center().x()+sinf(t)*bb.radius(), bb.center().y() + cosf(t)*bb.radius(), bb.zMax() + bb.radius() ,1.0f);
}
else
{
lightpos.set(sinf(t),cosf(t),1.0f,0.0f);
}
ls->getLight()->setPosition(lightpos);
osg::Vec3 dir = bb.center()-osg::Vec3(lightpos.x(),lightpos.y(),lightpos.z());
dir.normalize();
ls->getLight()->setDirection(dir);
} else {
float t = 0.23f;
lightpos.set(bb.center().x()+sinf(t)*bb.radius(), bb.center().y() + cosf(t)*bb.radius(), bb.zMax() + bb.radius() ,1.0f);
ls->getLight()->setPosition(lightpos);
osg::Vec3 dir = bb.center()-osg::Vec3(lightpos.x(),lightpos.y(),lightpos.z());
dir.normalize();
ls->getLight()->setDirection(dir);
}
viewer.frame();
}
#else
viewer.run();
#endif
}
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org