Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OSG shadows #978

Merged
merged 19 commits into from
Feb 17, 2018
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion dart/gui/osg/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ endif()
if(DART_BUILD_GUI_OSG)

find_package(OpenSceneGraph 3.0 QUIET
COMPONENTS osg osgViewer osgManipulator osgGA osgDB)
COMPONENTS osg osgViewer osgManipulator osgGA osgDB osgShadow)

# It seems that OPENSCENEGRAPH_FOUND will inadvertently get set to true when
# OpenThreads is found, even if OpenSceneGraph is not installed. This is quite
Expand Down
124 changes: 115 additions & 9 deletions dart/gui/osg/Viewer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@
#include <osg/OperationThread>
#include <osgDB/WriteFile>

#include <osgShadow/ShadowedScene>
#include <osgShadow/ShadowVolume>
#include <osgShadow/ShadowTexture>
#include <osgShadow/ShadowMap>
#include <osgShadow/StandardShadowMap>
#include <osgShadow/SoftShadowMap>

#include "dart/gui/osg/Viewer.hpp"
#include "dart/gui/osg/TrackballManipulator.hpp"
#include "dart/gui/osg/DefaultEventHandler.hpp"
Expand Down Expand Up @@ -190,7 +197,7 @@ void ViewerAttachment::attach(Viewer* newViewer)
}

//==============================================================================
Viewer::Viewer(const ::osg::Vec4& clearColor)
Viewer::Viewer(const ::osg::Vec4& clearColor, bool shadowsOn, ShadowType shadowType)
: mImageSequenceNum(0),
mImageDigits(0),
mRecording(false),
Expand All @@ -206,6 +213,11 @@ Viewer::Viewer(const ::osg::Vec4& clearColor)
mAllowSimulation(true),
mHeadlights(true)
{
enableShadows(shadowsOn, shadowType);

// add the physics group to the root group
mRootGroup->addChild(mPhysicsGroup);

setCameraManipulator(new osg::TrackballManipulator);
addInstructionText("Left-click: Interaction\n");
addInstructionText("Right-click: Rotate view\n");
Expand All @@ -215,12 +227,12 @@ Viewer::Viewer(const ::osg::Vec4& clearColor)
mDefaultEventHandler = new DefaultEventHandler(this);
// ^ Cannot construct this in the initialization list, because its constructor calls member functions of this object

setSceneData(mRootGroup);
addEventHandler(mDefaultEventHandler);
setupDefaultLights();
getCamera()->setClearColor(clearColor);

getCamera()->setFinalDrawCallback(new SaveScreen(this));

setSceneData(mRootGroup.get());
}

//==============================================================================
Expand Down Expand Up @@ -375,7 +387,7 @@ void Viewer::addWorldNode(WorldNode* _newWorldNode, bool _active)
return;

mWorldNodes[_newWorldNode] = _active;
mRootGroup->addChild(_newWorldNode);
mPhysicsGroup->addChild(_newWorldNode);
if(_active)
_newWorldNode->simulate(mSimulating);
_newWorldNode->mViewer = this;
Expand All @@ -389,7 +401,7 @@ void Viewer::removeWorldNode(WorldNode* _oldWorldNode)
if(it == mWorldNodes.end())
return;

mRootGroup->removeChild(it->first);
mPhysicsGroup->removeChild(it->first);
mWorldNodes.erase(it);
}

Expand All @@ -401,7 +413,7 @@ void Viewer::removeWorldNode(std::shared_ptr<dart::simulation::World> _oldWorld)
if(nullptr == node)
return;

mRootGroup->removeChild(node);
mPhysicsGroup->removeChild(node);
mWorldNodes.erase(node);
}

Expand Down Expand Up @@ -474,7 +486,7 @@ void Viewer::setupDefaultLights()
setUpwardsDirection(mUpwards);
switchHeadlights(true);

::osg::ref_ptr<::osg::StateSet> lightSS = mRootGroup->getOrCreateStateSet();
::osg::ref_ptr<::osg::StateSet> lightSS = mPhysicsGroup->getOrCreateStateSet();

mLight1->setLightNum(1);
mLightSource1->setLight(mLight1);
Expand All @@ -490,8 +502,8 @@ void Viewer::setupDefaultLights()
mLightGroup->removeChild(mLightSource2);
mLightGroup->addChild(mLightSource2);

mRootGroup->removeChild(mLightGroup);
mRootGroup->addChild(mLightGroup);
mPhysicsGroup->removeChild(mLightGroup);
mPhysicsGroup->addChild(mLightGroup);
}

//==============================================================================
Expand Down Expand Up @@ -831,6 +843,100 @@ const ::osg::ref_ptr<::osg::Group>& Viewer::getRootGroup() const
return mRootGroup;
}

//==============================================================================
const ::osg::ref_ptr<::osg::Group>& Viewer::getPhysicsGroup() const
{
return mPhysicsGroup;
}

//==============================================================================
bool Viewer::isShadowed() const
{
return mShadowed;
}

//==============================================================================
void Viewer::enableShadows(bool _enable, ShadowType type)
{
if(!mPhysicsGroup) {
// Flags for shadowing; maybe this needs to be global?
constexpr int ReceivesShadowTraversalMask = 0x2;
constexpr int CastsShadowTraversalMask = 0x1;

// Setup shadows
// Create one ShadowedScene for each light
::osg::ref_ptr<osgShadow::ShadowedScene> shadowedScene = new osgShadow::ShadowedScene;
shadowedScene->setReceivesShadowTraversalMask(ReceivesShadowTraversalMask);
shadowedScene->setCastsShadowTraversalMask(CastsShadowTraversalMask);

// set the physics group
mPhysicsGroup = shadowedScene.get();
mPhysicsGroup->getOrCreateStateSet();

setupDefaultLights();
}

if(_enable) {
switch(type) {
case ShadowType::STANDARD_SHADOW_MAP:
{
// Use the StandardShadowMap technique
::osg::ref_ptr<osgShadow::StandardShadowMap> ssm = new osgShadow::StandardShadowMap;
// we are using Light1 because this is the highest one (on up direction)
ssm->setLight(mLight1);
// set the technique
static_cast<osgShadow::ShadowedScene*>(mPhysicsGroup.get())->setShadowTechnique(ssm.get());
break;
}
case ShadowType::SOFT_SHADOW_MAP:
{
// Use the SoftShadowMap technique
::osg::ref_ptr<osgShadow::SoftShadowMap> softsm = new osgShadow::SoftShadowMap;
// we are using Light1 because this is the highest one (on up direction)
softsm->setLight(mLight1);
// set the technique
static_cast<osgShadow::ShadowedScene*>(mPhysicsGroup.get())->setShadowTechnique(softsm.get());
break;
}
case ShadowType::SHADOW_TEXTURE:
{
// Use the ShadowTexture technique
::osg::ref_ptr<osgShadow::ShadowTexture> st = new osgShadow::ShadowTexture;
// set the technique
static_cast<osgShadow::ShadowedScene*>(mPhysicsGroup.get())->setShadowTechnique(st.get());
break;
}
case ShadowType::SHADOW_VOLUME:
{
// hint to tell viewer to request stencil buffer when setting up windows
::osg::DisplaySettings::instance()->setMinimumNumStencilBits(8);
// Use the ShadowVolume technique
::osg::ref_ptr<osgShadow::ShadowVolume> sv = new osgShadow::ShadowVolume;
// set the technique
static_cast<osgShadow::ShadowedScene*>(mPhysicsGroup.get())->setShadowTechnique(sv.get());
break;
}
default: // SHADOW_MAP
{
// Use the ShadowMap technique
::osg::ref_ptr<osgShadow::ShadowMap> sm = new osgShadow::ShadowMap;
// increase the resolution of default shadow texture for higher quality
int mapres = std::pow(2, 13);
sm->setTextureSize(::osg::Vec2s(mapres,mapres));
// we are using Light1 because this is the highest one (on up direction)
sm->setLight(mLight1);
// set the technique
static_cast<osgShadow::ShadowedScene*>(mPhysicsGroup.get())->setShadowTechnique(sm.get());
break;
}
}
}
else
static_cast<osgShadow::ShadowedScene*>(mPhysicsGroup.get())->setShadowTechnique(0);

mShadowed = _enable;
}

} // namespace osg
} // namespace gui
} // namespace dart
23 changes: 22 additions & 1 deletion dart/gui/osg/Viewer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,18 @@ class Viewer : public osgViewer::Viewer, public dart::common::Subject
{
public:

enum ShadowType {
SHADOW_MAP = 0,
STANDARD_SHADOW_MAP,
SOFT_SHADOW_MAP,
SHADOW_TEXTURE,
SHADOW_VOLUME
// TODO: Add more techniques
};

/// Constructor for dart::gui::osg::Viewer. This will automatically create the
/// default event handler.
Viewer(const ::osg::Vec4& clearColor = ::osg::Vec4(0.9,0.9,0.9,1.0));
Viewer(const ::osg::Vec4& clearColor = ::osg::Vec4(0.9,0.9,0.9,1.0), bool shadowsOn = false, ShadowType shadowType = ShadowType::SHADOW_MAP);

/// Destructor
virtual ~Viewer();
Expand Down Expand Up @@ -288,6 +297,12 @@ class Viewer : public osgViewer::Viewer, public dart::common::Subject
/// Get the root ::osg::Group of this Viewer
const ::osg::ref_ptr<::osg::Group>& getRootGroup() const;

/// Get the physics root ::osg::Group of this Viewer
const ::osg::ref_ptr<::osg::Group>& getPhysicsGroup() const;

bool isShadowed() const;
void enableShadows(bool _enable = true, ShadowType type = ShadowType::SHADOW_MAP);

protected:

friend class SaveScreen;
Expand Down Expand Up @@ -319,6 +334,12 @@ class Viewer : public osgViewer::Viewer, public dart::common::Subject
/// The root node of this Viewer
::osg::ref_ptr<::osg::Group> mRootGroup;

/// The DART physics node of this Viewer
::osg::ref_ptr<::osg::Group> mPhysicsGroup;

/// Whether the shadows are enabled
bool mShadowed;

/// The Group Node containing light sources
::osg::ref_ptr<::osg::Group> mLightGroup;

Expand Down