建立独立的OSG程序

来源:互联网 发布:千锋教育java怎么样 编辑:程序博客网 时间:2024/05/29 11:43
  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 individually142     // 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);//设置渲染顺序为POST150     hudCamera->setClearMask(GL_DEPTH_BUFFER_BIT);//清除深度缓存151     152     //设置字体,声明一个timesFont,初始化为times.ttf153     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);//设置字体位置,用到上面申明的position174         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);//设置渲染顺序为POST261         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     else308     {309         osgViewer::Viewer viewer;310 311 312         // add all the camera manipulators313         {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 picking342         viewer.addEventHandler(new PickHandler(updateText.get()));343 344         // set the scene to render345         viewer.setSceneData(group.get());346     347         return viewer.run();348     }349 350 }

 

0 0
原创粉丝点击