-
Notifications
You must be signed in to change notification settings - Fork 287
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
OSG shadows #978
Changes from 15 commits
70b6d2f
a4b6cb4
6559528
3747652
53b8a05
1fd3aec
6a3c530
104e0e4
ab72b9d
47b7e41
a996028
62bb1ef
68dc5db
5ddba86
d7b83e8
c05a17f
d0d3b82
6ec3005
568631e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,6 +9,7 @@ TAGS | |
.DS_Store | ||
.cproject | ||
.project | ||
.vscode | ||
*.orig | ||
*.idb | ||
*.pdb | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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" | ||
|
@@ -61,12 +65,33 @@ class WorldNodeCallback : public ::osg::NodeCallback | |
}; | ||
|
||
//============================================================================== | ||
WorldNode::WorldNode(std::shared_ptr<dart::simulation::World> _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 physics group | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nitpick: This is called |
||
mShadowedGroup = shadowedScene.get(); | ||
mShadowedGroup->getOrCreateStateSet(); | ||
|
||
// Add normal and shadowed groups | ||
addChild(mNormalGroup); | ||
addChild(mShadowedGroup); | ||
|
||
setShadowTechnique(shadowTechnique); | ||
|
||
setUpdateCallback(new WorldNodeCallback); | ||
} | ||
|
||
|
@@ -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); | ||
} | ||
} | ||
|
@@ -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; | ||
} | ||
|
@@ -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 | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,6 +34,7 @@ | |
#define DART_GUI_OSG_WORLDNODE_HPP_ | ||
|
||
#include <osg/Group> | ||
#include <osgShadow/ShadowTechnique> | ||
#include <unordered_map> | ||
#include <memory> | ||
|
||
|
@@ -67,7 +68,8 @@ 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); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm still a little bit leery about having However, we do already have a precedent of this pattern where passing in a I might feel better about this pattern if we rename the argument from Sorry if this sounds petty, but without something along these lines, a user would have to look into the source code to actually understand how these functions should be used. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
No worries. I understand what you say. Nevertheless, in this version of the code, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, sorry, I didn't notice that part of the recent change. I actually liked providing a default shadow technique; I just wasn't comfortable with the semantics of "giving a I'm not clear on how a static default would work, since it seems to need information about the Viewer that's using it. I guess we could make it a factory function that takes a Since the shadows conflict with the ImGui feature, I suppose we should have shadows turned off by default anyway. It would've been nice to have shadows on by default, but we can tackle that later once we've fixed the ImGui conflict. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
That's exactly what I had in mind.. A static member function that creates a default
I agree on this and that's the reason I left the shadows disabled by default.. 😄 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was also thinking of modifying the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That sounds like a great place to put an example of this, thanks! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: Please remove the leading underscore from |
||
|
||
/// Set the World that this WorldNode is associated with | ||
void setWorld(std::shared_ptr<dart::simulation::World> _newWorld); | ||
|
@@ -129,6 +131,21 @@ class WorldNode : public ::osg::Group | |
/// 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 | ||
|
@@ -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 | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Please use
std::size_t
for index parameters.