From 8a995f6af97d1bc6ec5f252c3db8ced8dbb767fd Mon Sep 17 00:00:00 2001 From: Konstantinos Chatzilygeroudis Date: Tue, 6 Feb 2018 16:33:27 +0100 Subject: [PATCH 1/5] Adding Shadows to osg-gui --- dart/gui/osg/CMakeLists.txt | 2 +- dart/gui/osg/Viewer.cpp | 35 ++++++++++++++++++++--------------- dart/gui/osg/WorldNode.cpp | 27 ++++++++++++++++++++++++++- dart/gui/osg/WorldNode.hpp | 5 ++++- 4 files changed, 51 insertions(+), 18 deletions(-) diff --git a/dart/gui/osg/CMakeLists.txt b/dart/gui/osg/CMakeLists.txt index 9d943f0d81772..2787bd1eeeaa0 100644 --- a/dart/gui/osg/CMakeLists.txt +++ b/dart/gui/osg/CMakeLists.txt @@ -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 diff --git a/dart/gui/osg/Viewer.cpp b/dart/gui/osg/Viewer.cpp index 29b261e55fd26..1149ddb9a524b 100644 --- a/dart/gui/osg/Viewer.cpp +++ b/dart/gui/osg/Viewer.cpp @@ -316,32 +316,34 @@ void Viewer::switchHeadlights(bool _on) if(_on) { + // Turn on lights if(getLight()) { - getLight()->setAmbient(::osg::Vec4(0.1,0.1,0.1,1.0)); - getLight()->setDiffuse(::osg::Vec4(0.8,0.8,0.8,1.0)); + getLight()->setAmbient(::osg::Vec4(0.1,0.1,0.1,1.0)); // small ambient lighting is always desirable + getLight()->setDiffuse(::osg::Vec4(1.0,1.0,1.0,1.0)); getLight()->setSpecular(::osg::Vec4(1.0,1.0,1.0,1.0)); } if(mLight1) { mLight1->setAmbient(::osg::Vec4(0.0,0.0,0.0,1.0)); - mLight1->setDiffuse(::osg::Vec4(0.0,0.0,0.0,1.0)); - mLight1->setSpecular(::osg::Vec4(0.0,0.0,0.0,1.0)); + mLight1->setDiffuse(::osg::Vec4(1.0,1.0,1.0,1.0)); + mLight1->setSpecular(::osg::Vec4(1.0,1.0,1.0,1.0)); } if(mLight2) { mLight2->setAmbient(::osg::Vec4(0.0,0.0,0.0,1.0)); - mLight2->setDiffuse(::osg::Vec4(0.0,0.0,0.0,1.0)); - mLight2->setSpecular(::osg::Vec4(0.0,0.0,0.0,1.0)); + mLight1->setDiffuse(::osg::Vec4(1.0,1.0,1.0,1.0)); + mLight1->setSpecular(::osg::Vec4(1.0,1.0,1.0,1.0)); } } else { + // Turn off lights if(getLight()) { - getLight()->setAmbient(::osg::Vec4(0.1,0.1,0.1,1.0)); + getLight()->setAmbient(::osg::Vec4(0.1,0.1,0.1,1.0)); // small ambient lighting is always desirable getLight()->setDiffuse(::osg::Vec4(0.0,0.0,0.0,1.0)); getLight()->setSpecular(::osg::Vec4(0.0,0.0,0.0,1.0)); } @@ -349,15 +351,15 @@ void Viewer::switchHeadlights(bool _on) if(mLight1) { mLight1->setAmbient(::osg::Vec4(0.0,0.0,0.0,1.0)); - mLight1->setDiffuse(::osg::Vec4(0.7,0.7,0.7,1.0)); - mLight1->setSpecular(::osg::Vec4(0.9,0.9,0.9,1.0)); + mLight1->setDiffuse(::osg::Vec4(0.0,0.0,0.0,1.0)); + mLight1->setSpecular(::osg::Vec4(0.0,0.0,0.0,1.0)); } if(mLight2) { mLight2->setAmbient(::osg::Vec4(0.0,0.0,0.0,1.0)); - mLight2->setDiffuse(::osg::Vec4(0.3,0.3,0.3,1.0)); - mLight2->setSpecular(::osg::Vec4(0.4,0.4,0.4,1.0)); + mLight2->setDiffuse(::osg::Vec4(0.0,0.0,0.0,1.0)); + mLight2->setSpecular(::osg::Vec4(0.0,0.0,0.0,1.0)); } } } @@ -508,10 +510,13 @@ void Viewer::setUpwardsDirection(const ::osg::Vec3& _up) mOver = ::osg::Vec3(0,0,1)^_up; mOver.normalize(); - ::osg::Vec3 p1 = mUpwards+mOver; - mLight1->setPosition(::osg::Vec4(p1[0], p1[1], p1[2], 0.0)); - ::osg::Vec3 p2 = mUpwards-mOver; - mLight2->setPosition(::osg::Vec4(p2[0], p2[1], p2[2], 0.0)); + ::osg::Vec3 p1 = mUpwards*2.+mOver; + mLight1->setPosition(::osg::Vec4(p1[0], p1[1], p1[2], 1.0)); // 1.0 at the end means point or spot light + // default is point light since the spot cutoff is set at 180 degrees by default + mLight1->setQuadraticAttenuation(1.); // enable quadratic attenuation for more realistic lighting + ::osg::Vec3 p2 = mUpwards*2.-mOver; + mLight2->setPosition(::osg::Vec4(p2[0], p2[1], p2[2], 1.0)); // 1.0 at the end means point or spot light + mLight2->setQuadraticAttenuation(1.); // enable quadratic attenuation for more realistic lighting } //============================================================================== diff --git a/dart/gui/osg/WorldNode.cpp b/dart/gui/osg/WorldNode.cpp index 7b5508438623b..3d16214c05a7a 100644 --- a/dart/gui/osg/WorldNode.cpp +++ b/dart/gui/osg/WorldNode.cpp @@ -33,6 +33,8 @@ #include #include +#include +#include #include "dart/gui/osg/WorldNode.hpp" #include "dart/gui/osg/ShapeFrameNode.hpp" @@ -164,7 +166,30 @@ WorldNode::~WorldNode() //============================================================================== void WorldNode::setupViewer() { - // Do nothing + constexpr int ReceivesShadowTraversalMask = 0x2; + constexpr int CastsShadowTraversalMask = 0x1; + + // Setup shadows + // Create the ShadowedScene + ::osg::ref_ptr shadowedScene = new osgShadow::ShadowedScene; + shadowedScene->setReceivesShadowTraversalMask(ReceivesShadowTraversalMask); + shadowedScene->setCastsShadowTraversalMask(CastsShadowTraversalMask); + // Use the ShadowMap technique + ::osg::ref_ptr 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)); + + // set the technique + shadowedScene->setShadowTechnique(sm.get()); + + // add the Viewer's root object to the shadowed scene + shadowedScene->addChild(mViewer->getRootGroup().get()); + + // save the shadowed scene + mShadowedScene = shadowedScene; + // replace the viewer's scene data with the shadowed scene + mViewer->setSceneData(mShadowedScene.get()); } //============================================================================== diff --git a/dart/gui/osg/WorldNode.hpp b/dart/gui/osg/WorldNode.hpp index 4a272e777c5d5..950d5c1f1151b 100644 --- a/dart/gui/osg/WorldNode.hpp +++ b/dart/gui/osg/WorldNode.hpp @@ -136,7 +136,7 @@ class WorldNode : public ::osg::Group /// Called when this world gets added to an dart::gui::osg::Viewer. Override /// this function to customize the way your WorldNode starts up in an - /// dart::gui::osg::Viewer. Default behavior does nothing. + /// dart::gui::osg::Viewer. Default behavior enables shadows. virtual void setupViewer(); /// Clear the utilization flags of each child node @@ -173,6 +173,9 @@ class WorldNode : public ::osg::Group /// Viewer that this WorldNode is inside of Viewer* mViewer; + /// Osg ShadowedScene for handling shadows + ::osg::ref_ptr<::osg::Group> mShadowedScene; + }; } // namespace osg From a3d7dc662e87fc772b47ebcfa2837ae37fd3a10e Mon Sep 17 00:00:00 2001 From: Konstantinos Chatzilygeroudis Date: Tue, 6 Feb 2018 17:17:15 +0100 Subject: [PATCH 2/5] Split Shadows in different WorldNode --- dart/gui/osg/WorldNode.cpp | 27 +-------------------------- dart/gui/osg/WorldNode.hpp | 2 +- 2 files changed, 2 insertions(+), 27 deletions(-) diff --git a/dart/gui/osg/WorldNode.cpp b/dart/gui/osg/WorldNode.cpp index 3d16214c05a7a..7b5508438623b 100644 --- a/dart/gui/osg/WorldNode.cpp +++ b/dart/gui/osg/WorldNode.cpp @@ -33,8 +33,6 @@ #include #include -#include -#include #include "dart/gui/osg/WorldNode.hpp" #include "dart/gui/osg/ShapeFrameNode.hpp" @@ -166,30 +164,7 @@ WorldNode::~WorldNode() //============================================================================== void WorldNode::setupViewer() { - constexpr int ReceivesShadowTraversalMask = 0x2; - constexpr int CastsShadowTraversalMask = 0x1; - - // Setup shadows - // Create the ShadowedScene - ::osg::ref_ptr shadowedScene = new osgShadow::ShadowedScene; - shadowedScene->setReceivesShadowTraversalMask(ReceivesShadowTraversalMask); - shadowedScene->setCastsShadowTraversalMask(CastsShadowTraversalMask); - // Use the ShadowMap technique - ::osg::ref_ptr 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)); - - // set the technique - shadowedScene->setShadowTechnique(sm.get()); - - // add the Viewer's root object to the shadowed scene - shadowedScene->addChild(mViewer->getRootGroup().get()); - - // save the shadowed scene - mShadowedScene = shadowedScene; - // replace the viewer's scene data with the shadowed scene - mViewer->setSceneData(mShadowedScene.get()); + // Do nothing } //============================================================================== diff --git a/dart/gui/osg/WorldNode.hpp b/dart/gui/osg/WorldNode.hpp index 950d5c1f1151b..015683f8d698e 100644 --- a/dart/gui/osg/WorldNode.hpp +++ b/dart/gui/osg/WorldNode.hpp @@ -136,7 +136,7 @@ class WorldNode : public ::osg::Group /// Called when this world gets added to an dart::gui::osg::Viewer. Override /// this function to customize the way your WorldNode starts up in an - /// dart::gui::osg::Viewer. Default behavior enables shadows. + /// dart::gui::osg::Viewer. Default behavior does nothing. virtual void setupViewer(); /// Clear the utilization flags of each child node From 9cd37345dee83ae70bb291224a8625e8b2a67056 Mon Sep 17 00:00:00 2001 From: Konstantinos Chatzilygeroudis Date: Tue, 6 Feb 2018 17:18:38 +0100 Subject: [PATCH 3/5] Split Shadows in different WorldNode --- dart/gui/osg/ShadowedWorldNode.cpp | 77 ++++++++++++++++++++++++++++++ dart/gui/osg/ShadowedWorldNode.hpp | 65 +++++++++++++++++++++++++ dart/gui/osg/WorldNode.hpp | 3 -- 3 files changed, 142 insertions(+), 3 deletions(-) create mode 100644 dart/gui/osg/ShadowedWorldNode.cpp create mode 100644 dart/gui/osg/ShadowedWorldNode.hpp diff --git a/dart/gui/osg/ShadowedWorldNode.cpp b/dart/gui/osg/ShadowedWorldNode.cpp new file mode 100644 index 0000000000000..e41ffef0bbf5f --- /dev/null +++ b/dart/gui/osg/ShadowedWorldNode.cpp @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2011-2017, The DART development contributors + * All rights reserved. + * + * The list of contributors can be found at: + * https://github.com/dartsim/dart/blob/master/LICENSE + * + * This file is provided under the following "BSD-style" License: + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include "dart/gui/osg/ShadowedWorldNode.hpp" + +namespace dart { +namespace gui { +namespace osg { + +//============================================================================== +ShadowedWorldNode::ShadowedWorldNode(std::shared_ptr _world) + : WorldNode(_world) {} + +//============================================================================== +void ShadowedWorldNode::setupViewer() +{ + constexpr int ReceivesShadowTraversalMask = 0x2; + constexpr int CastsShadowTraversalMask = 0x1; + + // Setup shadows + // Create the ShadowedScene + ::osg::ref_ptr shadowedScene = new osgShadow::ShadowedScene; + shadowedScene->setReceivesShadowTraversalMask(ReceivesShadowTraversalMask); + shadowedScene->setCastsShadowTraversalMask(CastsShadowTraversalMask); + // Use the ShadowMap technique + ::osg::ref_ptr 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)); + + // set the technique + shadowedScene->setShadowTechnique(sm.get()); + + // add the Viewer's root object to the shadowed scene + shadowedScene->addChild(mViewer->getRootGroup().get()); + + // save the shadowed scene + mShadowedScene = shadowedScene; + // replace the viewer's scene data with the shadowed scene + mViewer->setSceneData(mShadowedScene.get()); +} + +} // namespace osg +} // namespace gui +} // namespace dart \ No newline at end of file diff --git a/dart/gui/osg/ShadowedWorldNode.hpp b/dart/gui/osg/ShadowedWorldNode.hpp new file mode 100644 index 0000000000000..2d1d2dc4c77ca --- /dev/null +++ b/dart/gui/osg/ShadowedWorldNode.hpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2011-2017, The DART development contributors + * All rights reserved. + * + * The list of contributors can be found at: + * https://github.com/dartsim/dart/blob/master/LICENSE + * + * This file is provided under the following "BSD-style" License: + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef DART_GUI_OSG_SHADOWEDWORLDNODE_HPP_ +#define DART_GUI_OSG_SHADOWEDWORLDNODE_HPP_ + +#include "dart/gui/osg/WorldNode.hpp" + +namespace dart { +namespace gui { +namespace osg { + +/// ShadowedWorldNode class encapsulates a World to be displayed in OpenSceneGraph with shadows +class ShadowedWorldNode : public WorldNode +{ +public: + + /// Default constructor + explicit ShadowedWorldNode(std::shared_ptr _world = nullptr); + +protected: + /// Called when this world gets added to an dart::gui::osg::Viewer. Override + /// this function to customize the way your WorldNode starts up in an + /// dart::gui::osg::Viewer. Default behavior enables shadows. + void setupViewer(); + + /// Osg ShadowedScene for handling shadows + ::osg::ref_ptr<::osg::Group> mShadowedScene; + +}; + +} // namespace osg +} // namespace gui +} // namespace dart + +#endif // DART_GUI_OSG_SHADOWEDWORLDNODE_HPP_ diff --git a/dart/gui/osg/WorldNode.hpp b/dart/gui/osg/WorldNode.hpp index 015683f8d698e..4a272e777c5d5 100644 --- a/dart/gui/osg/WorldNode.hpp +++ b/dart/gui/osg/WorldNode.hpp @@ -173,9 +173,6 @@ class WorldNode : public ::osg::Group /// Viewer that this WorldNode is inside of Viewer* mViewer; - /// Osg ShadowedScene for handling shadows - ::osg::ref_ptr<::osg::Group> mShadowedScene; - }; } // namespace osg From 0ae7cdc1ce173c35c17f8f5cd2e719f180871b65 Mon Sep 17 00:00:00 2001 From: Konstantinos Chatzilygeroudis Date: Wed, 7 Feb 2018 01:29:42 +0100 Subject: [PATCH 4/5] Fix for shadow behavior --- dart/gui/osg/ShadowedWorldNode.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/dart/gui/osg/ShadowedWorldNode.cpp b/dart/gui/osg/ShadowedWorldNode.cpp index e41ffef0bbf5f..c8b767c970971 100644 --- a/dart/gui/osg/ShadowedWorldNode.cpp +++ b/dart/gui/osg/ShadowedWorldNode.cpp @@ -68,8 +68,15 @@ void ShadowedWorldNode::setupViewer() // save the shadowed scene mShadowedScene = shadowedScene; + // get camera's home position + // it is reseted when chaning the SceneData, which can lead to undesired behavior + ::osg::Vec3d eye, center, up; + mViewer->getCameraManipulator()->getHomePosition(eye, center, up); // replace the viewer's scene data with the shadowed scene mViewer->setSceneData(mShadowedScene.get()); + // reset the home position + mViewer->getCameraManipulator()->setHomePosition(eye, center, up); + mViewer->home(); } } // namespace osg From 551340c9fc46026dc374247e04f2f8580f950ded Mon Sep 17 00:00:00 2001 From: Konstantinos Chatzilygeroudis Date: Wed, 7 Feb 2018 01:30:30 +0100 Subject: [PATCH 5/5] Typos in comments --- dart/gui/osg/ShadowedWorldNode.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dart/gui/osg/ShadowedWorldNode.cpp b/dart/gui/osg/ShadowedWorldNode.cpp index c8b767c970971..810e9fb604a74 100644 --- a/dart/gui/osg/ShadowedWorldNode.cpp +++ b/dart/gui/osg/ShadowedWorldNode.cpp @@ -69,7 +69,7 @@ void ShadowedWorldNode::setupViewer() // save the shadowed scene mShadowedScene = shadowedScene; // get camera's home position - // it is reseted when chaning the SceneData, which can lead to undesired behavior + // it is resetted when changing the SceneData, which can lead to undesired behavior ::osg::Vec3d eye, center, up; mViewer->getCameraManipulator()->getHomePosition(eye, center, up); // replace the viewer's scene data with the shadowed scene