1 /* OpenSceneGraph example, osgcallback.
2 *
3 *  Permission is hereby granted, free of charge, to any person obtaining a copy
4 *  of this software and associated documentation files (the "Software"), to deal
5 *  in the Software without restriction, including without limitation the rights
6 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 *  copies of the Software, and to permit persons to whom the Software is
8 *  furnished to do so, subject to the following conditions:
9 *
10 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
11 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
12 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
13 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
14 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
15 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
16 *  THE SOFTWARE.
17 */
18 
19 #include <osgViewer/Viewer>
20 
21 #include <osg/Transform>
22 #include <osg/Billboard>
23 #include <osg/Geode>
24 #include <osg/Group>
25 #include <osg/Notify>
26 
27 #include <osgDB/Registry>
28 #include <osgDB/ReadFile>
29 
30 #include <osgGA/TrackballManipulator>
31 #include <osgGA/FlightManipulator>
32 #include <osgGA/DriveManipulator>
33 
34 #include <osgUtil/Optimizer>
35 
36 #include <iostream>
37 
38 class UpdateCallback : public osg::NodeCallback
39 {
operator ()(osg::Node * node,osg::NodeVisitor * nv)40         virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
41         {
42             std::cout<<"update callback - pre traverse"<<node<<std::endl;
43             traverse(node,nv);
44             std::cout<<"update callback - post traverse"<<node<<std::endl;
45         }
46 };
47 
48 class CullCallback : public osg::NodeCallback
49 {
operator ()(osg::Node * node,osg::NodeVisitor * nv)50         virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
51         {
52             std::cout<<"cull callback - pre traverse"<<node<<std::endl;
53             traverse(node,nv);
54             std::cout<<"cull callback - post traverse"<<node<<std::endl;
55         }
56 };
57 
58 class DrawableDrawCallback : public osg::Drawable::DrawCallback
59 {
drawImplementation(osg::RenderInfo & renderInfo,const osg::Drawable * drawable) const60         virtual void drawImplementation(osg::RenderInfo& renderInfo,const osg::Drawable* drawable) const
61         {
62             std::cout<<"draw call back - pre drawImplementation"<<drawable<<std::endl;
63             drawable->drawImplementation(renderInfo);
64             std::cout<<"draw call back - post drawImplementation"<<drawable<<std::endl;
65         }
66 };
67 
68 struct DrawableUpdateCallback : public osg::Drawable::UpdateCallback
69 {
updateDrawableUpdateCallback70     virtual void update(osg::NodeVisitor*, osg::Drawable* drawable)
71     {
72         std::cout<<"Drawable update callback "<<drawable<<std::endl;
73     }
74 };
75 
76 struct DrawableCullCallback : public osg::Drawable::CullCallback
77 {
78     /** do customized cull code.*/
cullDrawableCullCallback79     virtual bool cull(osg::NodeVisitor*, osg::Drawable* drawable, osg::State* /*state*/) const
80     {
81         std::cout<<"Drawable cull callback "<<drawable<<std::endl;
82         return false;
83     }
84 };
85 
86 class InsertCallbacksVisitor : public osg::NodeVisitor
87 {
88 
89    public:
90 
InsertCallbacksVisitor()91         InsertCallbacksVisitor():osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
92         {
93         }
94 
apply(osg::Node & node)95         virtual void apply(osg::Node& node)
96         {
97              node.setUpdateCallback(new UpdateCallback());
98              node.setCullCallback(new CullCallback());
99              traverse(node);
100         }
101 
apply(osg::Geode & geode)102         virtual void apply(osg::Geode& geode)
103         {
104             geode.setUpdateCallback(new UpdateCallback());
105 
106             //note, it makes no sense to attach a cull callback to the node
107             //at there are no nodes to traverse below the geode, only
108             //drawables, and as such the Cull node callbacks is ignored.
109             //If you wish to control the culling of drawables
110             //then use a drawable cullback...
111 
112             for(unsigned int i=0;i<geode.getNumDrawables();++i)
113             {
114                 geode.getDrawable(i)->setUpdateCallback(new DrawableUpdateCallback());
115                 geode.getDrawable(i)->setCullCallback(new DrawableCullCallback());
116                 geode.getDrawable(i)->setDrawCallback(new DrawableDrawCallback());
117             }
118         }
119 
apply(osg::Transform & node)120         virtual void apply(osg::Transform& node)
121         {
122             apply((osg::Node&)node);
123         }
124 };
125 
126 class MyReadFileCallback : public osgDB::Registry::ReadFileCallback
127 {
128 public:
readNode(const std::string & fileName,const osgDB::ReaderWriter::Options * options)129     virtual osgDB::ReaderWriter::ReadResult readNode(const std::string& fileName, const osgDB::ReaderWriter::Options* options)
130     {
131         std::cout<<"before readNode"<<std::endl;
132         // note when calling the Registry to do the read you have to call readNodeImplementation NOT readNode, as this will
133         // cause on infinite recusive loop.
134         osgDB::ReaderWriter::ReadResult result = osgDB::Registry::instance()->readNodeImplementation(fileName,options);
135         std::cout<<"after readNode"<<std::endl;
136         return result;
137     }
138 };
139 
140 class CameraUpdateCallback : public osg::NodeCallback
141 {
operator ()(osg::Node * node,osg::NodeVisitor * nv)142     virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
143     {
144         std::cout<<"Camera update callback - pre traverse"<<node<<std::endl;
145         traverse(node,nv);
146         std::cout<<"Camera update callback - post traverse"<<node<<std::endl;
147     }
148 };
149 
150 class CameraEventCallback : public osg::NodeCallback
151 {
operator ()(osg::Node * node,osg::NodeVisitor * nv)152     virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
153     {
154         std::cout<<"Camera event callback - pre traverse"<<node<<std::endl;
155         traverse(node,nv);
156         std::cout<<"Camera event callback - post traverse"<<node<<std::endl;
157     }
158 };
159 
160 
161 struct TestDrawableUpdateCallback : public osg::Drawable::UpdateCallback
162 {
TestDrawableUpdateCallbackTestDrawableUpdateCallback163     TestDrawableUpdateCallback(const std::string &message): _message(message) {}
164 
updateTestDrawableUpdateCallback165     virtual void update(osg::NodeVisitor*, osg::Drawable* drw) {
166         printf("%s\n", _message.c_str());
167     }
168     std::string _message;
169 };
170 
171 struct TestNodeUpdateCallback : public osg::NodeCallback
172 {
TestNodeUpdateCallbackTestNodeUpdateCallback173     TestNodeUpdateCallback(const std::string &message): _message(message) {}
174 
operator ()TestNodeUpdateCallback175     virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) {
176         printf("%s\n", _message.c_str());
177     }
178     std::string _message;
179 };
180 
181 
main(int argc,char ** argv)182 int main( int argc, char **argv )
183 {
184     // use an ArgumentParser object to manage the program arguments.
185     osg::ArgumentParser arguments(&argc,argv);
186 
187     // set the osgDB::Registy read file callback to catch all requests for reading files.
188     osgDB::Registry::instance()->setReadFileCallback(new MyReadFileCallback());
189 
190     // initialize the viewer.
191     osgViewer::Viewer viewer;
192 
193     // load the nodes from the commandline arguments.
194     osg::ref_ptr<osg::Node> rootnode;
195 
196     if (arguments.read("--test"))
197     {
198         osg::ref_ptr<osg::Group> root = new osg::Group();
199         rootnode = root;
200 
201         osg::Node *test1 = new osg::Node();
202         test1->setUpdateCallback(new TestNodeUpdateCallback("test1"));
203         root->addChild(test1);
204 
205         osg::Drawable *test2 = new osg::Drawable();
206         test2->osg::Node::setUpdateCallback(new TestNodeUpdateCallback("test2"));
207         root->addChild(test2);
208 
209         osg::Drawable *test3 = new osg::Drawable();
210         test3->setUpdateCallback(new TestDrawableUpdateCallback("test3"));
211         root->addChild(test3);
212 
213         osg::Geode *test4 = new osg::Geode();
214         osg::Drawable *drawable1 = new osg::Drawable();
215         drawable1->osg::Node::setUpdateCallback(new TestNodeUpdateCallback("test4"));
216         test4->addDrawable(drawable1);
217         root->addChild(test4);
218 
219         osg::Geode *test5 = new osg::Geode();
220         osg::Drawable *drawable2 = new osg::Drawable();
221         drawable2->setUpdateCallback(new TestDrawableUpdateCallback("test5"));
222         test5->addDrawable(drawable2);
223         root->addChild(test5);
224 
225         osg::Geode *test6 = new osg::Geode();
226         osg::Drawable *drawable3 = new osg::Drawable();
227         drawable3->setUpdateCallback(new TestDrawableUpdateCallback("test6"));
228         test6->addChild(drawable3);
229         root->addChild(test6);
230 
231         osg::Geode *test7 = new osg::Geode();
232         osg::Drawable *drawable4 = new osg::Drawable();
233         drawable4->osg::Node::setUpdateCallback(new TestNodeUpdateCallback("test7"));
234         test7->addChild(drawable4);
235         root->addChild(test7);
236 
237         printf("Numchildren with updates %u\n", rootnode->getNumChildrenRequiringUpdateTraversal());
238 
239     }
240     else
241     {
242         rootnode = osgDB::readRefNodeFiles(arguments);
243 
244         // if not loaded assume no arguments passed in, try use default mode instead.
245         if (!rootnode) rootnode = osgDB::readRefNodeFile("cow.osgt");
246 
247         if (!rootnode)
248         {
249             osg::notify(osg::NOTICE)<<"Please specify a file on the command line"<<std::endl;
250 
251             return 1;
252         }
253 
254         // run optimization over the scene graph
255         osgUtil::Optimizer optimzer;
256         optimzer.optimize(rootnode.get());
257 
258         // insert all the callbacks
259         InsertCallbacksVisitor icv;
260         rootnode->accept(icv);
261     }
262 
263     viewer.getCamera()->setUpdateCallback(new CameraUpdateCallback());
264     viewer.getCamera()->setEventCallback(new CameraEventCallback());
265 
266     // set the scene to render
267     viewer.setSceneData(rootnode.get());
268 
269     viewer.setCameraManipulator(new osgGA::TrackballManipulator);
270 
271     viewer.realize();
272 
273     while(!viewer.done())
274     {
275         OSG_NOTICE<<std::endl<<"New Frame"<<std::endl;
276         viewer.frame();
277     }
278 
279     return 0;
280 }
281