1 /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2  *
3  * This library is open source and may be redistributed and/or modified under
4  * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5  * (at your option) any later version.  The full license is in LICENSE file
6  * included with this distribution, and on the openscenegraph.org website.
7  *
8  * This library is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * OpenSceneGraph Public License for more details.
12 */
13 
14 #include <osgViewer/Scene>
15 #include <osgGA/EventVisitor>
16 
17 using namespace osgViewer;
18 
19 
20 namespace osgViewer
21 {
22 
23 
24 struct SceneSingleton
25 {
SceneSingletonosgViewer::SceneSingleton26     SceneSingleton() {}
27 
addosgViewer::SceneSingleton28     inline void add(Scene* scene)
29     {
30         OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
31         _cache.push_back(scene);
32     }
33 
removeosgViewer::SceneSingleton34     inline void remove(Scene* scene)
35     {
36         OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
37         for(SceneCache::iterator itr = _cache.begin();
38             itr != _cache.end();
39             ++itr)
40         {
41             if (scene==itr->get())
42             {
43                 _cache.erase(itr);
44                 break;
45             }
46         }
47     }
48 
getSceneosgViewer::SceneSingleton49     inline Scene* getScene(osg::Node* node)
50     {
51         OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
52         for(SceneCache::iterator itr = _cache.begin();
53             itr != _cache.end();
54             ++itr)
55         {
56             Scene* scene = itr->get();
57             if (scene && scene->getSceneData()==node) return scene;
58         }
59         return 0;
60     }
61 
62     typedef std::vector< osg::observer_ptr<Scene> >  SceneCache;
63     SceneCache          _cache;
64     OpenThreads::Mutex  _mutex;
65 };
66 
getSceneSingleton()67 static SceneSingleton& getSceneSingleton()
68 {
69     static SceneSingleton s_sceneSingleton;
70     return s_sceneSingleton;
71 }
72 
73 // Use a proxy to force the initialization of the SceneSingleton during static initialization
74 OSG_INIT_SINGLETON_PROXY(SceneSingletonProxy, getSceneSingleton())
75 
76 }
77 
Scene()78 Scene::Scene():
79     osg::Referenced(true)
80 {
81     setDatabasePager(osgDB::DatabasePager::create());
82     setImagePager(new osgDB::ImagePager);
83     getSceneSingleton().add(this);
84 }
85 
~Scene()86 Scene::~Scene()
87 {
88     getSceneSingleton().remove(this);
89 }
90 
setSceneData(osg::Node * node)91 void Scene::setSceneData(osg::Node* node)
92 {
93     _sceneData = node;
94 }
95 
getSceneData()96 osg::Node* Scene::getSceneData()
97 {
98     return _sceneData.get();
99 }
100 
getSceneData() const101 const osg::Node* Scene::getSceneData() const
102 {
103     return _sceneData.get();
104 }
105 
setDatabasePager(osgDB::DatabasePager * dp)106 void Scene::setDatabasePager(osgDB::DatabasePager* dp)
107 {
108     _databasePager = dp;
109 }
110 
setImagePager(osgDB::ImagePager * ip)111 void Scene::setImagePager(osgDB::ImagePager* ip)
112 {
113     _imagePager = ip;
114 }
115 
updateSceneGraph(osg::NodeVisitor & updateVisitor)116 void Scene::updateSceneGraph(osg::NodeVisitor& updateVisitor)
117 {
118     if (!_sceneData) return;
119 
120     if (getDatabasePager())
121     {
122         // synchronize changes required by the DatabasePager thread to the scene graph
123         getDatabasePager()->updateSceneGraph((*updateVisitor.getFrameStamp()));
124     }
125 
126     if (getImagePager())
127     {
128         // synchronize changes required by the DatabasePager thread to the scene graph
129         getImagePager()->updateSceneGraph(*(updateVisitor.getFrameStamp()));
130     }
131 
132     if (getSceneData())
133     {
134         updateVisitor.setImageRequestHandler(getImagePager());
135         getSceneData()->accept(updateVisitor);
136     }
137 }
138 
139 
getScene(osg::Node * node)140 Scene* Scene::getScene(osg::Node* node)
141 {
142     return getSceneSingleton().getScene(node);
143     return 0;
144 }
145 
getOrCreateScene(osg::Node * node)146 Scene* Scene::getOrCreateScene(osg::Node* node)
147 {
148     if (!node) return 0;
149 
150     osgViewer::Scene* scene = getScene(node);
151     if (!scene)
152     {
153         scene = new Scene;
154         scene->setSceneData(node);
155     }
156 
157     return scene;
158 }
159