【转】osgCallback的实现方法
综述,可以得出回调的编写方法:
1、编写用户结构体,继承OSG中响应的虚函数结构图,如osg::NodeCallback;
2、重载回调执行函数,根据回调种类的不同,执行函数的名称也不同,可以参考osgCallBack中的设置
3、注意在回调执行的过程中,有一些必要的系统操作需要交由用户来完成,例如readNodeImplementation,Drawable::drawImplementation,traverse等,否则系统本身的渲染工作可能会不正常。
编译运行osgcallback之后,可以看到控制台不断输出各种回调的执行结果,用户可以根据自己的需要在不同的时间段进入不同的回调来完成所需的工作。
参考文章地址:http://www.360doc.com/content/14/0619/23/12278894_388198735.shtml
1 //更新遍历,重载操作符operator,当场景更新时,operator()的内容被调用,注意 2 3 //需要添加traverse()以实现节点的继续遍历。可以参考src/osg/stateset.cpp,runUpdateCallBack()中的调用 4 5 class UpdateCallback : public osg::NodeCallback 6 7 { 8 9 virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) 10 11 { 12 13 std::cout<<"update callback - pre traverse"<<node<<std::endl; 14 15 traverse(node,nv); 16 17 std::cout<<"update callback - post traverse"<<node<<std::endl; 18 19 } 20 21 }; 22 23 24 25 //拣选遍历,重载操作符operator(),当场景执行拣选优化时,operator()被调用,注意 26 27 //需要添加traverse()以实现节点的继续遍历,可以参考include/osgUtil/CullVisitor, 28 29 //handle_cull_callbacks_and_traverse()中的调用过程。 30 31 class CullCallback : public osg::NodeCallback 32 33 { 34 35 virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) 36 37 { 38 39 std::cout<<"cull callback - pre traverse"<<node<<std::endl; 40 41 traverse(node,nv); 42 43 std::cout<<"cull callback - post traverse"<<node<<std::endl; 44 45 } 46 47 }; 48 49 50 51 //几何体绘制遍历,重载drawImplementation(),当几何体进行绘制时,函数的内容被调用,否则 52 53 //将无法画出当前的几何形状。可以参考include/osg/Drawable,draw()中的调用过程 54 55 class DrawableDrawCallback : public osg::Drawable::DrawCallback 56 57 { 58 59 virtual void drawImplementation(osg::RenderInfo& renderInfo,const osg::Drawable* drawable) const 60 61 { 62 63 std::cout<<"draw call back - pre drawImplementation"<<drawable<<std::endl; 64 65 drawable->drawImplementation(renderInfo); 66 67 std::cout<<"draw call back - post drawImplementation"<<drawable<<std::endl; 68 69 } 70 71 }; 72 73 74 75 //几何体更新遍历,重载函数update().当几何体更新时,其函数被调用。可以参考 76 77 //include/osgUtil/UpdateVisitor, handle_geode_callback()中的调用过程。 78 79 struct DrawableUpdateCallback : public osg::Drawable::UpdateCallback 80 81 { 82 83 virtual void update(osg::NodeVisitor*, osg::Drawable* drawable) 84 85 { 86 87 std::cout<<"Drawable update callback "<<drawable<<std::endl; 88 89 } 90 91 }; 92 93 94 95 //几何体拣选遍历,重载函数cull。当几何体进行拣选优化时,函数的内容被调用。可以参考 96 97 //src/osgutil/cullVisitor, apply(Geode&)函数中的调用过程 98 99 struct DrawableCullCallback : public osg::Drawable::CullCallback 100 101 { 102 103 /** do customized cull code.*/ 104 105 virtual bool cull(osg::NodeVisitor*, osg::Drawable* drawable, osg::State* /*state*/) const 106 107 { 108 109 std::cout<<"Drawable cull callback "<<drawable<<std::endl; 110 111 return false; 112 113 } 114 115 }; 116 117 118 119 class InsertCallbacksVisitor : public osg::NodeVisitor 120 121 { 122 123 124 125 public: 126 127 128 129 InsertCallbacksVisitor():osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) 130 131 { 132 133 } 134 135 136 137 virtual void apply(osg::Node& node) 138 139 { 140 141 node.setUpdateCallback(new UpdateCallback()); 142 143 node.setCullCallback(new CullCallback()); 144 145 traverse(node); 146 147 } 148 149 150 151 virtual void apply(osg::Geode& geode) 152 153 { 154 155 geode.setUpdateCallback(new UpdateCallback()); 156 157 158 159 //note, it makes no sense to attach a cull callback to the node 160 161 //at there are no nodes to traverse below the geode, only 162 163 //drawables, and as such the Cull node callbacks is ignored. 164 165 //If you wish to control the culling of drawables 166 167 //then use a drawable cullback... 168 169 170 171 for(unsigned int i=0;i<geode.getNumDrawables();++i) 172 173 { 174 175 geode.getDrawable(i)->setUpdateCallback(new DrawableUpdateCallback()); 176 177 geode.getDrawable(i)->setCullCallback(new DrawableCullCallback()); 178 179 geode.getDrawable(i)->setDrawCallback(new DrawableDrawCallback()); 180 181 } 182 183 } 184 185 186 187 virtual void apply(osg::Transform& node) 188 189 { 190 191 apply((osg::Node&)node); 192 193 } 194 195 }; 196 197 198 199 class MyReadFileCallback : public osgDB::Registry::ReadFileCallback 200 201 { 202 203 public: 204 205 virtual osgDB::ReaderWriter::ReadResult readNode(const std::string& fileName, const osgDB::ReaderWriter::Options* options) 206 207 { 208 209 std::cout<<"before readNode"<<std::endl; 210 211 // note when calling the Registry to do the read you have to call readNodeImplementation NOT readNode, as this will 212 213 // cause on infinite recusive loop. 214 215 osgDB::ReaderWriter::ReadResult result = osgDB::Registry::instance()->readNodeImplementation(fileName,options); 216 217 std::cout<<"after readNode"<<std::endl; 218 219 return result; 220 221 } 222 223 }; 224 225 226 227 class CameraUpdateCallback : public osg::NodeCallback 228 229 { 230 231 virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) 232 233 { 234 235 std::cout<<"Camera update callback - pre traverse"<<node<<std::endl; 236 237 traverse(node,nv); 238 239 std::cout<<"Camera update callback - post traverse"<<node<<std::endl; 240 241 } 242 243 }; 244 245 246 247 class CameraEventCallback : public osg::NodeCallback 248 249 { 250 251 virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) 252 253 { 254 255 std::cout<<"Camera event callback - pre traverse"<<node<<std::endl; 256 257 traverse(node,nv); 258 259 std::cout<<"Camera event callback - post traverse"<<node<<std::endl; 260 261 } 262 263 }; 264 265 266 267 int main( int argc, char **argv ) 268 269 { 270 271 // use an ArgumentParser object to manage the program arguments. 272 273 osg::ArgumentParser arguments(&argc,argv); 274 275 276 277 // set the osgDB::Registy read file callback to catch all requests for reading files. 278 279 osgDB::Registry::instance()->setReadFileCallback(new MyReadFileCallback()); 280 281 282 283 // initialize the viewer. 284 285 osgViewer::Viewer viewer; 286 287 288 289 // load the nodes from the commandline arguments. 290 291 osg::Node* rootnode = osgDB::readNodeFiles(arguments); 292 293 294 295 // if not loaded assume no arguments passed in, try use default mode instead. 296 297 if (!rootnode) rootnode = osgDB::readNodeFile("cow.osgt"); 298 299 300 301 if (!rootnode) 302 303 { 304 305 osg::notify(osg::NOTICE)<<"Please specify a file on the command line"<<std::endl; 306 307 308 309 return 1; 310 311 } 312 313 314 315 // run optimization over the scene graph 316 317 osgUtil::Optimizer optimzer; 318 319 optimzer.optimize(rootnode); 320 321 322 323 // insert all the callbacks 324 325 InsertCallbacksVisitor icv; 326 327 rootnode->accept(icv); 328 329 330 331 viewer.getCamera()->setUpdateCallback(new CameraUpdateCallback()); 332 333 viewer.getCamera()->setEventCallback(new CameraEventCallback()); 334 335 336 337 // set the scene to render 338 339 viewer.setSceneData(rootnode); 340 341 342 343 return viewer.run(); 344 345 }
OSG源码中回调函数的执行过程
1 //当你为你的节点设置了回调函数 2 3 node.setUpdateCallback(new UpdateCallback()); 4 5 6 7 void ViewerBase::frame(double simulationTime) 8 9 { 10 11 updateTraversal(); /帧循环,更新回调 12 13 } 14 15 16 17 //回调函数的执行过程 18 19 20 21 void Viewer::updateTraversal() 22 23 { 24 25 ......... 26 27 _scene->updateSceneGraph(*_updateVisitor);//_updateVisitor为osgUtil::UpdateVisitor,用来负责场景更新遍历 28 29 30 31 ......... 32 33 } 34 35 36 37 void Scene::updateSceneGraph(osg::NodeVisitor& updateVisitor) 38 39 { 40 41 42 43 if (getSceneData()) 44 45 { 46 47 updateVisitor.setImageRequestHandler(getImagePager()); 48 49 getSceneData()->accept(updateVisitor); 50 51 } 52 53 } 54 55 56 57 void Node::accept(osg::NodeVisitor& nv) { 58 59 if (nv.validNodeMask(*this)) 60 61 { 62 63 nv.pushOntoNodePath(this); nv.apply(*this); nv.popFromNodePath(); 64 65 } 66 67 } 68 69 70 71 void UpdateVisitor::apply(osg::Group& node) 72 73 { handle_callbacks_and_traverse(node); } 74 75 76 77 78 79 inline void handle_callbacks_and_traverse(osg::Node& node) 80 81 { 82 83 handle_callbacks(node.getStateSet()); 84 85 osg::NodeCallback* callback = node.getUpdateCallback(); 86 87 if (callback) (*callback)(&node,this); 88 89 90 91 else if (node.getNumChildrenRequiringUpdateTraversal()>0) traverse(node); 92 93 } <strong> 94 95 </strong>