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 all 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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ TAGS
.DS_Store
.cproject
.project
.vscode
*.orig
*.idb
*.pdb
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
* GUI

* Added support of rendering texture images: [#973](https://github.com/dartsim/dart/pull/973)
* Added OSG shadows: [#978](https://github.com/dartsim/dart/pull/978)

* License

Expand Down
6 changes: 4 additions & 2 deletions dart/dynamics/ShapeFrame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,11 @@ namespace detail {

//==============================================================================
VisualAspectProperties::VisualAspectProperties(const Eigen::Vector4d& color,
const bool hidden)
const bool hidden,
const bool shadowed)
: mRGBA(color),
mHidden(hidden)
mHidden(hidden),
mShadowed(shadowed)
{
// Do nothing
}
Expand Down
9 changes: 6 additions & 3 deletions dart/dynamics/ShapeFrame.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,15 @@ class VisualAspect final :
void setRGBA(const Eigen::Vector4d& color);

DART_COMMON_GET_ASPECT_PROPERTY( Eigen::Vector4d, RGBA )
// void setRGBA(const Eigen::Vector4d& value);
// const Eigen::Vector4d& getRGBA() const;

DART_COMMON_SET_GET_ASPECT_PROPERTY( bool, Hidden )
// void setHidden(const Eigen::Vector4d& value);
// const Eigen::Vector4d& getHidden() const;
// void setHidden(const bool& value);
// const bool& getHidden() const;

DART_COMMON_SET_GET_ASPECT_PROPERTY( bool, Shadowed )
// void setShadowed(const bool& value);
// const bool& getShadowed() const;

/// Identical to setRGB(const Eigen::Vector3d&)
void setColor(const Eigen::Vector3d& color);
Expand Down
6 changes: 5 additions & 1 deletion dart/dynamics/detail/ShapeFrameAspect.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,14 @@ struct VisualAspectProperties
/// True if this shape node should be kept from rendering
bool mHidden;

/// True if this shape node should be shadowed
bool mShadowed;

/// Constructor
VisualAspectProperties(
const Eigen::Vector4d& color = Eigen::Vector4d(0.5, 0.5, 1.0, 1.0),
const bool hidden = false);
const bool hidden = false,
const bool shadowed = true);

/// Destructor
virtual ~VisualAspectProperties() = default;
Expand Down
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
4 changes: 4 additions & 0 deletions dart/gui/osg/InteractiveFrame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ dart::dynamics::SimpleFrame* InteractiveTool::addShapeFrame(
auto shapeFrame = mSimpleFrames.back().get();
shapeFrame->setShape(shape);
shapeFrame->createVisualAspect();
// Disable shadowing for InteractiveTool
shapeFrame->getVisualAspect(true)->setShadowed(false);

return shapeFrame;
}
Expand Down Expand Up @@ -230,6 +232,8 @@ dart::dynamics::SimpleFrame* InteractiveFrame::addShapeFrame(
auto shapeFrame = mSimpleFrames.back().get();
shapeFrame->setShape(shape);
shapeFrame->createVisualAspect();
// Disable shadowing for InteractiveFrame
shapeFrame->getVisualAspect(true)->setShadowed(false);

return shapeFrame;
}
Expand Down
12 changes: 12 additions & 0 deletions dart/gui/osg/Viewer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,9 @@ void Viewer::addWorldNode(WorldNode* _newWorldNode, bool _active)
_newWorldNode->simulate(mSimulating);
_newWorldNode->mViewer = this;
_newWorldNode->setupViewer();
// set again the shadow technique to produce warning for ImGuiViewer
if(_newWorldNode->isShadowed())
_newWorldNode->setShadowTechnique(_newWorldNode->getShadowTechnique());
}

//==============================================================================
Expand Down Expand Up @@ -468,6 +471,15 @@ const ::osg::Group* Viewer::getLightGroup() const
return mLightGroup;
}

//==============================================================================
const ::osg::ref_ptr<::osg::LightSource>& Viewer::getLightSource(std::size_t index) const
{
assert(index < 2);
if(index == 0)
return mLightSource1;
return mLightSource2;
}

//==============================================================================
void Viewer::setupDefaultLights()
{
Expand Down
7 changes: 6 additions & 1 deletion dart/gui/osg/Viewer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include <memory>

#include <osgViewer/Viewer>
#include <osgShadow/ShadowTechnique>

#include <Eigen/Core>

Expand Down Expand Up @@ -114,7 +115,6 @@ class ViewerAttachment : public virtual ::osg::Group
class Viewer : public osgViewer::Viewer, public dart::common::Subject
{
public:

/// 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));
Expand Down Expand Up @@ -197,6 +197,11 @@ class Viewer : public osgViewer::Viewer, public dart::common::Subject
/// Get the Group node that contains the LightSources for this Viewer
const ::osg::Group* getLightGroup() const;

/// Get one of the LightSources of this Viewer
/// index either 0 or 1
/// Useful for shadowing techniques
const ::osg::ref_ptr<::osg::LightSource>& getLightSource(std::size_t index = 0) const;

/// Set up the default lighting scheme
void setupDefaultLights();

Expand Down
106 changes: 95 additions & 11 deletions dart/gui/osg/WorldNode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,12 @@

#include <osg/NodeCallback>

#include <osgShadow/ShadowedScene>
#include <osgShadow/ShadowMap>

#include "dart/gui/osg/WorldNode.hpp"
#include "dart/gui/osg/ShapeFrameNode.hpp"
#include "dart/gui/osg/ImGuiViewer.hpp"

#include "dart/simulation/World.hpp"
#include "dart/dynamics/Skeleton.hpp"
Expand All @@ -61,19 +65,40 @@ class WorldNodeCallback : public ::osg::NodeCallback
};

//==============================================================================
WorldNode::WorldNode(std::shared_ptr<dart::simulation::World> _world)
: mWorld(_world),
WorldNode::WorldNode(std::shared_ptr<dart::simulation::World> world, ::osg::ref_ptr<osgShadow::ShadowTechnique> shadowTechnique)
: mWorld(world),
mSimulating(false),
mNumStepsPerCycle(1),
mViewer(nullptr)
mViewer(nullptr),
mNormalGroup(new ::osg::Group)
{
// Flags for shadowing; maybe this needs to be global?
constexpr int ReceivesShadowTraversalMask = 0x2;
constexpr int CastsShadowTraversalMask = 0x1;

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

// set the shadowed group
mShadowedGroup = shadowedScene.get();
mShadowedGroup->getOrCreateStateSet();

// Add normal and shadowed groups
addChild(mNormalGroup);
addChild(mShadowedGroup);

setShadowTechnique(shadowTechnique);

setUpdateCallback(new WorldNodeCallback);
}

//==============================================================================
void WorldNode::setWorld(std::shared_ptr<dart::simulation::World> _newWorld)
void WorldNode::setWorld(std::shared_ptr<dart::simulation::World> newWorld)
{
mWorld = _newWorld;
mWorld = newWorld;
}

//==============================================================================
Expand Down Expand Up @@ -138,15 +163,15 @@ bool WorldNode::isSimulating() const
}

//==============================================================================
void WorldNode::simulate(bool _on)
void WorldNode::simulate(bool on)
{
mSimulating = _on;
mSimulating = on;
}

//==============================================================================
void WorldNode::setNumStepsPerCycle(std::size_t _steps)
void WorldNode::setNumStepsPerCycle(std::size_t steps)
{
mNumStepsPerCycle = _steps;
mNumStepsPerCycle = steps;
}

//==============================================================================
Expand Down Expand Up @@ -193,7 +218,11 @@ void WorldNode::clearUnusedNodes()
{
NodeMap::iterator it = mFrameToNode.find(frame);
ShapeFrameNode* node = it->second;
removeChild(node);
if(!node->getShapeFrame() || !node->getShapeFrame()->hasVisualAspect() || !node->getShapeFrame()->getVisualAspect(true)->getShadowed()) {
mNormalGroup->removeChild(node);
}
else
mShadowedGroup->removeChild(node);
mFrameToNode.erase(it);
}
}
Expand Down Expand Up @@ -260,6 +289,16 @@ void WorldNode::refreshShapeFrameNode(dart::dynamics::Frame* frame)
if(!node)
return;

// update the group that ShapeFrameNode should be
if((!node->getShapeFrame()->hasVisualAspect() || !node->getShapeFrame()->getVisualAspect(true)->getShadowed()) && node->getParent(0) != mNormalGroup) {
mShadowedGroup->removeChild(node);
mNormalGroup->addChild(node);
}
else if(node->getShapeFrame()->hasVisualAspect() && node->getShapeFrame()->getVisualAspect(true)->getShadowed() && node->getParent(0) != mShadowedGroup) {
mNormalGroup->removeChild(node);
mShadowedGroup->addChild(node);
}

node->refresh(true);
return;
}
Expand All @@ -276,7 +315,52 @@ void WorldNode::refreshShapeFrameNode(dart::dynamics::Frame* frame)
::osg::ref_ptr<ShapeFrameNode> node = new ShapeFrameNode(frame->asShapeFrame(),
this);
it->second = node;
addChild(node);
if(!node->getShapeFrame()->hasVisualAspect() || !node->getShapeFrame()->getVisualAspect(true)->getShadowed()) {
mNormalGroup->addChild(node);
}
else
mShadowedGroup->addChild(node);
}

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

//==============================================================================
void WorldNode::setShadowTechnique(::osg::ref_ptr<osgShadow::ShadowTechnique> shadowTechnique) {
if(!shadowTechnique) {
mShadowed = false;
static_cast<osgShadow::ShadowedScene*>(mShadowedGroup.get())->setShadowTechnique(nullptr);
}
else {
ImGuiViewer* viewer = mViewer ? dynamic_cast<ImGuiViewer*>(mViewer) : nullptr;
if(viewer)
dtwarn << "[WorldNode] You are enabling shadows inside an ImGuiViewer. "
<< "The ImGui windows may not render properly.\n";
mShadowed = true;
static_cast<osgShadow::ShadowedScene*>(mShadowedGroup.get())->setShadowTechnique(shadowTechnique.get());
}
}

//==============================================================================
::osg::ref_ptr<osgShadow::ShadowTechnique> WorldNode::getShadowTechnique() const {
if(!mShadowed)
return nullptr;
return static_cast<osgShadow::ShadowedScene*>(mShadowedGroup.get())->getShadowTechnique();
}

//==============================================================================
::osg::ref_ptr<osgShadow::ShadowTechnique> WorldNode::createDefaultShadowTechnique(const Viewer* viewer) {
::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(viewer->getLightSource(0));

return sm;
}

} // namespace osg
Expand Down
34 changes: 30 additions & 4 deletions dart/gui/osg/WorldNode.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#define DART_GUI_OSG_WORLDNODE_HPP_

#include <osg/Group>
#include <osgShadow/ShadowTechnique>
#include <unordered_map>
#include <memory>

Expand Down Expand Up @@ -67,10 +68,11 @@ class WorldNode : public ::osg::Group
friend class Viewer;

/// Default constructor
explicit WorldNode(std::shared_ptr<dart::simulation::World> _world = nullptr);
/// Shadows are disabled by default
explicit WorldNode(std::shared_ptr<dart::simulation::World> world = nullptr, ::osg::ref_ptr<osgShadow::ShadowTechnique> shadowTechnique = nullptr);

/// Set the World that this WorldNode is associated with
void setWorld(std::shared_ptr<dart::simulation::World> _newWorld);
void setWorld(std::shared_ptr<dart::simulation::World> newWorld);

/// Get the World that this WorldNode is associated with
std::shared_ptr<dart::simulation::World> getWorld() const;
Expand Down Expand Up @@ -119,16 +121,31 @@ class WorldNode : public ::osg::Group

/// Pass in true to take steps between render cycles; pass in false to turn
/// off steps between render cycles.
void simulate(bool _on);
void simulate(bool on);

/// Set the number of steps to take between each render cycle (only if the
/// simulation is not paused)
void setNumStepsPerCycle(std::size_t _steps);
void setNumStepsPerCycle(std::size_t steps);

/// Get the number of steps that will be taken between each render cycle (only
/// if the simulation is not paused)
std::size_t getNumStepsPerCycle() const;

/// Get whether the WorldNode is casting shadows
bool isShadowed() const;

/// Set the ShadowTechnique
/// If you wish to disable shadows, pass a nullptr
void setShadowTechnique(::osg::ref_ptr<osgShadow::ShadowTechnique> shadowTechnique = nullptr);

/// Get the current ShadowTechnique
/// nullptr is there are no shadows
::osg::ref_ptr<osgShadow::ShadowTechnique> getShadowTechnique() const;

/// Helper function to create a default ShadowTechnique given a Viewer
/// the default ShadowTechnique is ShadowMap
static ::osg::ref_ptr<osgShadow::ShadowTechnique> createDefaultShadowTechnique(const Viewer* viewer);

protected:

/// Destructor
Expand Down Expand Up @@ -173,6 +190,15 @@ class WorldNode : public ::osg::Group
/// Viewer that this WorldNode is inside of
Viewer* mViewer;

/// OSG group for non-shadowed objects
::osg::ref_ptr<::osg::Group> mNormalGroup;

/// OSG group for shadowed objects
::osg::ref_ptr<::osg::Group> mShadowedGroup;

/// Whether the shadows are enabled
bool mShadowed;

};

} // namespace osg
Expand Down
Loading