建立独立的OSG程序

  1 /* OpenSceneGraph example, osgpick.*/
  2 
  3 /* osgpick sample
  4 * demonstrate use of osgUtil/PickVisitor for picking in a HUD or
  5 * in a 3d scene,
  6 */
  7 
  8 #include <osgUtil/Optimizer>
  9 #include <osgDB/ReadFile>
 10 #include <osgViewer/Viewer>
 11 #include <osgViewer/CompositeViewer>
 12 
 13 #include <osgGA/TerrainManipulator>
 14 #include <osgGA/StateSetManipulator>
 15 #include <osgGA/AnimationPathManipulator>
 16 #include <osgGA/TrackballManipulator>
 17 #include <osgGA/FlightManipulator>
 18 #include <osgGA/DriveManipulator>
 19 #include <osgGA/KeySwitchMatrixManipulator>
 20 #include <osgGA/StateSetManipulator>
 21 #include <osgGA/AnimationPathManipulator>
 22 #include <osgGA/TerrainManipulator>
 23 
 24 #include <osg/Material>
 25 #include <osg/Geode>
 26 #include <osg/BlendFunc>
 27 #include <osg/Depth>
 28 #include <osg/Projection>
 29 #include <osg/MatrixTransform>
 30 #include <osg/Camera>
 31 #include <osg/io_utils>
 32 #include <osg/ShapeDrawable>
 33 
 34 #include <osgText/Text>
 35 
 36 #include <sstream>
 37 
 38 // 处理拾取事件的类,继承自osgGA::GUIEventhandler 界面事件处理
 39 class PickHandler : public osgGA::GUIEventHandler {
 40 public: 
 41     //构造函数
 42     PickHandler(osgText::Text* updateText):
 43         _updateText(updateText) {}
 44     //析构函数    
 45     ~PickHandler() {}
 46     //处理(事件接口、动作接口)
 47     bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa);
 48     //拾取(视图、事件接口)
 49     virtual void pick(osgViewer::View* view, const osgGA::GUIEventAdapter& ea);
 50     //设置显示内容
 51     void setLabel(const std::string& name)
 52     {
 53         if (_updateText.get()) 
 54             _updateText->setText(name);
 55     }
 56     
 57 protected:
 58     //传递一个文字对象
 59     osg::ref_ptr<osgText::Text>  _updateText;
 60 };
 61 //事件处理(事件接口、动作接口)
 62 bool PickHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa)
 63 {
 64     switch(ea.getEventType())
 65     {
 66         case(osgGA::GUIEventAdapter::PUSH):
 67         {
 68             //dynamic_cast运算符的作用是将&aa转换成osgViewer::View*类型的对象
 69             osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa);
 70             if (view) pick(view,ea);
 71             return false;
 72         }    
 73         case(osgGA::GUIEventAdapter::KEYDOWN):
 74         {
 75             if (ea.getKey()=='c')
 76             {        
 77                 osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa);
 78                 //event也是一个指针,类型是osgGA::GUIEventAdapter
 79                 osg::ref_ptr<osgGA::GUIEventAdapter> event = new osgGA::GUIEventAdapter(ea);
 80                 event->setX((ea.getXmin()+ea.getXmax())*0.5);
 81                 event->setY((ea.getYmin()+ea.getYmax())*0.5);
 82                 if (view) pick(view,*event);
 83             }
 84             return false;
 85         }    
 86         default:
 87             return false;
 88     }
 89 }
 90 
 91 //拾取(视图、事件接口)通过view计算交点 ,从事件接口ea中获得 x和y
 92 void PickHandler::pick(osgViewer::View* view, const osgGA::GUIEventAdapter& ea)
 93 {
 94     //创建一个线段交集检测对象
 95     osgUtil::LineSegmentIntersector::Intersections intersections;
 96 
 97     std::string gdlist="";
 98     //得到鼠标的位置 x和y
 99     float x = ea.getX();
100     float y = ea.getY();
101     
102     //如果发生交集运算 (即鼠标点中了物体)
103     if (view->computeIntersections(x,y,intersections))
104     {
105         //得到相交交集的交点, hitr是一个迭代器
106         for(osgUtil::LineSegmentIntersector::Intersections::iterator hitr = intersections.begin();
107             hitr != intersections.end();
108             ++hitr)
109         {
110             std::ostringstream os;//申请一个流
111             if (!hitr->nodePath.empty() && !(hitr->nodePath.back()->getName().empty()))
112             {
113                 // the geodes are identified by name.
114                 os<<"Object \""<<hitr->nodePath.back()->getName()<<"\""<<std::endl;
115             }
116             else if (hitr->drawable.valid())
117             {
118                 os<<"Object \""<<hitr->drawable->className()<<"\""<<std::endl;
119             }
120             //将局部坐标顶点和法线输入到os这个流里面。
121             os<<"        local coords vertex("<< hitr->getLocalIntersectPoint()<<")"<<"  normal("<<hitr->getLocalIntersectNormal()<<")"<<std::endl;
122             os<<"        world coords vertex("<< hitr->getWorldIntersectPoint()<<")"<<"  normal("<<hitr->getWorldIntersectNormal()<<")"<<std::endl;
123             //交点索引列表vil,交点存在hitr里面
124             const osgUtil::LineSegmentIntersector::Intersection::IndexList& vil = hitr->indexList;
125             for(unsigned int i=0;i<vil.size();++i)
126             {
127                 os<<"        vertex indices ["<<i<<"] = "<<vil[i]<<std::endl;
128             }
129             //gdlist是一个字符串,用来存os中要显示的文字
130             gdlist += os.str();
131         }
132     }
133     //设置显示内容
134     setLabel(gdlist);
135 }
136 //创建HUD 参数是osgText。HUD也是作为场景中的一个节点存在
137 osg::Node* createHUD(osgText::Text* updateText)
138 {
139 
140     // create the hud. derived from osgHud.cpp  (derived:来源于)
141     // adds a set of quads, each in a separate Geode - which can be picked individually
142     // eg to be used as a menuing/help system!
143     // Can pick texts too!
144 
145     osg::Camera* hudCamera = new osg::Camera;//创建一个相机
146     hudCamera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);//设置绝对帧引用
147     hudCamera->setProjectionMatrixAsOrtho2D(0,1280,0,1024);//设置正投影矩阵
148     hudCamera->setViewMatrix(osg::Matrix::identity());//设置视图矩阵
149     hudCamera->setRenderOrder(osg::Camera::POST_RENDER);//设置渲染顺序为POST
150     hudCamera->setClearMask(GL_DEPTH_BUFFER_BIT);//清除深度缓存
151     
152     //设置字体,声明一个timesFont,初始化为times.ttf
153     std::string timesFont("fonts/times.ttf");
154     
155     //关掉字体的光照、禁用深度缓存  来保证字体一直在最上面
156     
157     osg::Vec3 position(150.0f,800.0f,0.0f);//设置位置
158     osg::Vec3 delta(0.0f,-60.0f,0.0f);
159     
160     {
161         osg::Geode* geode = new osg::Geode();//也可以写成osg::ref_ptr<osg::Geode> geode  = new osg::Geode();-------geode就是一个指针
162         osg::StateSet* stateset = geode->getOrCreateStateSet();//状态设置
163         stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);//关闭光照
164         stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);//关闭深度缓存
165         geode->setName("simple");//设置这个geode的名字,geode是场景中的叶子节点
166         hudCamera->addChild(geode);
167         
168         osgText::Text* text = new  osgText::Text;
169         geode->addDrawable( text );//geode是osg场景中的叶子节点,然后就是让所有drawable的东西成组
170         
171         text->setFont(timesFont);//设置字体
172         text->setText("Picking in Head Up Displays is simple!\nHow to do it?\nAm I on the first quard?");//设置内容
173         text->setPosition(position);//设置字体位置,用到上面申明的position
174         
175         position += delta;
176     }    
177     
178     
179     for (int i=0; i<6; i++) {
180         osg::Vec3 dy(0.0f,-30.0f,0.0f);
181         osg::Vec3 dx(120.0f,0.0f,0.0f);
182         osg::Geode* geode = new osg::Geode();
183         osg::StateSet* stateset = geode->getOrCreateStateSet();
184         const char *opts[]={"One", "Two", "Three", "January", "Feb", "2003"};
185         osg::Geometry *quad=new osg::Geometry;//申明一个指向几何体的指针
186         stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
187         stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);
188         std::string name="subOption";
189         name += " ";
190         name += std::string(opts[i]);
191         geode->setName(name);//设置节点的名字
192         osg::Vec3Array* vertices = new osg::Vec3Array(4); // 1 quad,弄个3元数组指针,数组有4个元素,分别保存矩形的4个顶点
193         osg::Vec4Array* colors = new osg::Vec4Array;//4元数组指针 ,保存颜色
194         colors = new osg::Vec4Array;
195         colors->push_back(osg::Vec4(0.8-0.1*i, 0.1*i, 0.2*i, 1.0));//通过i的变化来实现块的渐变颜色
196         quad->setColorArray(colors);
197         quad->setColorBinding(osg::Geometry::BIND_PER_PRIMITIVE);//绑定颜色到方块上
198         (*vertices)[0]=position;
199         (*vertices)[1]=position+dx;
200         (*vertices)[2]=position+dx+dy;
201         (*vertices)[3]=position+dy;
202         quad->setVertexArray(vertices);//设置顶点数组
203         quad->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4));
204         geode->addDrawable(quad);
205         hudCamera->addChild(geode);
206         
207         position += delta;
208     }    
209     
210     
211     
212     { 
213         //这里显示什么被选中
214         osg::Geode* geode = new osg::Geode();
215         osg::StateSet* stateset = geode->getOrCreateStateSet();
216         stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
217         stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);
218         geode->setName("The text label");
219         geode->addDrawable( updateText );//这里的updateText是createHUD函数的传入参数
220         hudCamera->addChild(geode);
221         
222         updateText->setCharacterSize(20.0f);
223         updateText->setFont(timesFont);
224         updateText->setColor(osg::Vec4(1.0f,1.0f,0.0f,1.0f));
225         updateText->setText("");
226         updateText->setPosition(position);
227         updateText->setDataVariance(osg::Object::DYNAMIC);
228         
229         position += delta;
230     }    
231     
232     return hudCamera;
233 
234 }
235 
236 
237 //主函数
238 int main( int argc, char **argv )
239 {
240     //使用一个参数解析器对象来管理程序的参数
241     osg::ArgumentParser arguments(&argc,argv);
242 
243     //从命令行参数指定的文件列表中读取场景
244     osg::ref_ptr<osg::Node> scene = osgDB::readNodeFiles(arguments);
245     //如果场景没有创建成功
246     if (!scene && arguments.read("--relative-camera-scene"))
247     {
248            //创建一个带有相关引用帧的相机的测试场景
249         osg::Group* group = new osg::Group();
250 
251         osg::Geode* sphere = new osg::Geode();//创建一个球
252         sphere->setName("Sphere");
253         sphere->addDrawable(new osg::ShapeDrawable(new osg::Sphere()));
254 
255         osg::Geode* cube = new osg::Geode();//创建一个盒子
256         cube->setName("Cube");
257         cube->addDrawable(new osg::ShapeDrawable(new osg::Box()));
258 
259         osg::Camera* camera = new osg::Camera();//创建一个相机
260         camera->setRenderOrder(osg::Camera::POST_RENDER);//设置渲染顺序为POST
261         camera->setClearMask(GL_DEPTH_BUFFER_BIT);//清除深度缓存
262         camera->setReferenceFrame(osg::Transform::RELATIVE_RF);//设置相对帧引用
263         camera->setViewMatrix(osg::Matrix::translate(-2, 0, 0));//设置视图矩阵
264 
265         osg::MatrixTransform* xform = new osg::MatrixTransform(osg::Matrix::translate(1, 1, 1));
266         xform->addChild(camera);
267 
268         group->addChild(sphere);
269         group->addChild(xform);
270         camera->addChild(cube);
271 
272         scene = group;
273     }
274 
275     //如果没有载入假设的场景,没有参数传进来。试着使用默认的模型代替。
276     if (!scene) scene = osgDB::readNodeFile("fountain.osgt");
277 
278     osg::ref_ptr<osg::Group> group = dynamic_cast<osg::Group*>(scene.get());
279     if (!group)
280     {
281         group = new osg::Group;
282         group->addChild(scene.get());
283     }
284 
285     osg::ref_ptr<osgText::Text> updateText = new osgText::Text;
286 
287     // add the HUD subgraph.    
288     group->addChild(createHUD(updateText.get()));
289 
290     if (arguments.read("--CompositeViewer"))
291     {
292         osg::ref_ptr<osgViewer::View> view = new osgViewer::View;
293         // 添加处理拾取事件的handler到视图中
294         view->addEventHandler(new PickHandler(updateText.get()));
295 
296         // set the scene to render,设置场景到渲染中
297         view->setSceneData(group.get());
298 
299         view->setUpViewAcrossAllScreens();
300 
301         osgViewer::CompositeViewer viewer;
302         viewer.addView(view.get());
303 
304         return viewer.run();
305 
306     }
307     else
308     {
309         osgViewer::Viewer viewer;
310 
311 
312         // add all the camera manipulators
313         {
314             osg::ref_ptr<osgGA::KeySwitchMatrixManipulator> keyswitchManipulator = new osgGA::KeySwitchMatrixManipulator;
315 
316             keyswitchManipulator->addMatrixManipulator( '1', "Trackball", new osgGA::TrackballManipulator() );
317             keyswitchManipulator->addMatrixManipulator( '2', "Flight", new osgGA::FlightManipulator() );
318             keyswitchManipulator->addMatrixManipulator( '3', "Drive", new osgGA::DriveManipulator() );
319 
320             unsigned int num = keyswitchManipulator->getNumMatrixManipulators();
321             keyswitchManipulator->addMatrixManipulator( '4', "Terrain", new osgGA::TerrainManipulator() );
322 
323             std::string pathfile;
324             char keyForAnimationPath = '5';
325             while (arguments.read("-p",pathfile))
326             {
327                 osgGA::AnimationPathManipulator* apm = new osgGA::AnimationPathManipulator(pathfile);
328                 if (apm || !apm->valid()) 
329                 {
330                     num = keyswitchManipulator->getNumMatrixManipulators();
331                     keyswitchManipulator->addMatrixManipulator( keyForAnimationPath, "Path", apm );
332                     ++keyForAnimationPath;
333                 }
334             }
335 
336             keyswitchManipulator->selectMatrixManipulator(num);
337 
338             viewer.setCameraManipulator( keyswitchManipulator.get() );
339         }
340 
341         // add the handler for doing the picking
342         viewer.addEventHandler(new PickHandler(updateText.get()));
343 
344         // set the scene to render
345         viewer.setSceneData(group.get());
346     
347         return viewer.run();
348     }
349 
350 }

 

posted @ 2012-05-11 17:52  清凉一夏o0  阅读(828)  评论(0编辑  收藏  举报