1 /* 2 * Copyright (c) 2011-2021, The DART development contributors 3 * All rights reserved. 4 * 5 * The list of contributors can be found at: 6 * https://github.com/dartsim/dart/blob/master/LICENSE 7 * 8 * This file is provided under the following "BSD-style" License: 9 * Redistribution and use in source and binary forms, with or 10 * without modification, are permitted provided that the following 11 * conditions are met: 12 * * Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * * Redistributions in binary form must reproduce the above 15 * copyright notice, this list of conditions and the following 16 * disclaimer in the documentation and/or other materials provided 17 * with the distribution. 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 19 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 20 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 26 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 27 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 29 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #ifndef DART_GUI_OSG_WORLDNODE_HPP_ 34 #define DART_GUI_OSG_WORLDNODE_HPP_ 35 36 #include <memory> 37 #include <unordered_map> 38 #include <osg/Group> 39 #include <osgShadow/ShadowTechnique> 40 41 #include "dart/gui/osg/Viewer.hpp" 42 43 namespace dart { 44 45 namespace simulation { 46 class World; 47 } // namespace simulation 48 49 namespace dynamics { 50 class Frame; 51 class Entity; 52 class ShapeFrame; 53 } // namespace dynamics 54 55 namespace gui { 56 namespace osg { 57 58 class FrameNode; 59 class ShapeFrameNode; 60 class EntityNode; 61 class Viewer; 62 63 /// WorldNode class encapsulates a World to be displayed in OpenSceneGraph 64 class WorldNode : public ::osg::Group 65 { 66 public: 67 friend class Viewer; 68 69 /// Default constructor 70 /// Shadows are disabled by default 71 explicit WorldNode( 72 std::shared_ptr<dart::simulation::World> world = nullptr, 73 ::osg::ref_ptr<osgShadow::ShadowTechnique> shadowTechnique = nullptr); 74 75 /// Set the World that this WorldNode is associated with 76 void setWorld(std::shared_ptr<dart::simulation::World> newWorld); 77 78 /// Get the World that this WorldNode is associated with 79 std::shared_ptr<dart::simulation::World> getWorld() const; 80 81 /// This function is called at the beginning of each rendering cycle. It 82 /// updates the tree of Frames and Entities that need to be rendered. It may 83 /// also take a simulation step if the simulation is not paused. 84 /// 85 /// If you want to customize what happens at the beginning of each rendering 86 /// cycle, you can either overload this function, or you can overload 87 /// customUpdate(). This update() function will automatically call 88 /// customUpdate() at the beginning of each rendering cycle. By default, 89 /// customUpdate() does nothing. 90 virtual void refresh(); 91 92 /// If update() is not overloaded, this function will be called at the 93 /// beginning of each rendering cycle. This function can be overloaded to 94 /// customize the behavior of each update. The default behavior is to do 95 /// nothing, so overloading this function will not interfere with the usual 96 /// update() operation. 97 virtual void customPreRefresh(); 98 99 /// If update() is not overloaded, this function will be called at the end of 100 /// each rendering cycle. This function can be overloaded to customize the 101 /// behavior of each update. The default behavior is to do nothing, so 102 /// overloading this function will not interfere with the usual update() 103 /// operation. 104 virtual void customPostRefresh(); 105 106 /// If update() is not overloaded, this function will be called at the 107 /// beginning of each simulation step. This function can be overloaded to 108 /// customize the behavior of each step. The default behavior is to do 109 /// nothing, so overloading this function will not interfere with the usual 110 /// update() operation. This will not get called if the simulation is paused. 111 virtual void customPreStep(); 112 113 /// If update() is not overloaded, this function will be called at the end of 114 /// each simulation step. This function can be overloaded to customize the 115 /// behavior of each step. The default behavior is to do nothing, so 116 /// overloading this function will not interfere with the usual update() 117 /// operation. This will not get called if the simulation is paused. 118 virtual void customPostStep(); 119 120 /// Returns true iff the WorldNode is stepping between render cycles 121 bool isSimulating() const; 122 123 /// Pass in true to take steps between render cycles; pass in false to turn 124 /// off steps between render cycles. 125 void simulate(bool on); 126 127 /// Set the number of steps to take between each render cycle (only if the 128 /// simulation is not paused) 129 void setNumStepsPerCycle(std::size_t steps); 130 131 /// Get the number of steps that will be taken between each render cycle (only 132 /// if the simulation is not paused) 133 std::size_t getNumStepsPerCycle() const; 134 135 /// Get whether the WorldNode is casting shadows 136 bool isShadowed() const; 137 138 /// Set the ShadowTechnique 139 /// If you wish to disable shadows, pass a nullptr 140 void setShadowTechnique( 141 ::osg::ref_ptr<osgShadow::ShadowTechnique> shadowTechnique = nullptr); 142 143 /// Get the current ShadowTechnique 144 /// nullptr is there are no shadows 145 ::osg::ref_ptr<osgShadow::ShadowTechnique> getShadowTechnique() const; 146 147 /// Helper function to create a default ShadowTechnique given a Viewer 148 /// the default ShadowTechnique is ShadowMap 149 static ::osg::ref_ptr<osgShadow::ShadowTechnique> 150 createDefaultShadowTechnique(const Viewer* viewer); 151 152 /// Destructor 153 virtual ~WorldNode(); 154 155 protected: 156 /// Called when this world gets added to an dart::gui::osg::Viewer. Override 157 /// this function to customize the way your WorldNode starts up in an 158 /// dart::gui::osg::Viewer. Default behavior does nothing. 159 virtual void setupViewer(); 160 161 /// Clear the utilization flags of each child node 162 void clearChildUtilizationFlags(); 163 164 /// Clear any nodes whose utilization flags were not triggered on this render 165 /// cycle 166 void clearUnusedNodes(); 167 168 /// Refresh all the Skeleton rendering data 169 void refreshSkeletons(); 170 171 /// Refresh all the custom Frame rendering data 172 void refreshSimpleFrames(); 173 174 void refreshBaseFrameNode(dart::dynamics::Frame* frame); 175 176 void refreshShapeFrameNode(dart::dynamics::Frame* frame); 177 178 using NodeMap = std:: 179 unordered_map<dart::dynamics::Frame*, ::osg::ref_ptr<ShapeFrameNode>>; 180 181 /// Map from Frame pointers to FrameNode pointers 182 NodeMap mFrameToNode; 183 184 /// The World that this WorldNode is associated with 185 std::shared_ptr<dart::simulation::World> mWorld; 186 187 /// True iff simulation is active 188 bool mSimulating; 189 190 /// Number of steps to take between rendering cycles 191 std::size_t mNumStepsPerCycle; 192 193 /// Viewer that this WorldNode is inside of 194 Viewer* mViewer; 195 196 /// OSG group for non-shadowed objects 197 ::osg::ref_ptr<::osg::Group> mNormalGroup; 198 199 /// OSG group for shadowed objects 200 ::osg::ref_ptr<::osgShadow::ShadowedScene> mShadowedGroup; 201 202 /// Whether the shadows are enabled 203 bool mShadowed; 204 }; 205 206 } // namespace osg 207 } // namespace gui 208 } // namespace dart 209 210 #endif // DART_GUI_OSG_WORLDNODE_HPP_ 211