OSG教程:场景保存类Viewer

本文详细解析了OSG程序设计教程中的Viewer类,包括其构造函数、析构函数、继承图表以及关键成员函数。介绍了如何通过构造函数初始化Viewer对象,如何通过析构函数释放资源,以及如何通过成员函数进行场景数据设置、渲染操作和事件处理等。
来源: 第三维度
    作者:FreeSouth[杨石兴]编著

    选自《OSG程序设计教程》第二章第四节

    osgViewer::Viewer

    类描述: 为一个单独的场景[scene]保存一个单独的view.

    类中方法:

    1:Viewer()
    2:Viewer (osg::ArgumentParser &arguments)
    3:Viewer (const osgViewer::Viewer &viewer, const osg::CopyOp &copyop=osg::CopyOp::SHALLOW_COPY)

    说明:是Viewer的构造函数。其中第一个为常见的构造函数。第二个构造函数为从类osg::ArgumentParser中传递参数入Viewer,类ArgumentParser可以获取main入口参数以及程序的其它信息,也可以判断传参是否有误。第三个重载的构造函数为从另一个Viewer创建新Viewer,里面的第一个参数表示源Viewer,而第二个参数表示使用的拷贝类型,参数主要有两个,一个是浅拷贝:SHALLOW_COPY,另一个则是深拷贝:DEEP_COPY_OBJECTS,关于拷贝类型的不同和利弊可以参照一般C++书籍。关于OSG中的拷贝类型可以参照类osg::CopyOp。

    参数

OSG教程:场景保存类Viewer

    类继承图表:

OSG教程:场景保存类Viewer

    virtual ~Viewer ()

    说明: 析构函数

    META_Object (osgViewer, Viewer)

    说明:是一个宏,宏中定义了标准Clone,且具有isSameAs,ClassName,accept三个重要方法。目的是让从Node派生的子类方便的定义所需要的纯虚方法。

    参数

META_Object (osgViewer, Viewer)

    virtual void take (View &rhs)

    说明:功能是从一个View中得到它的所有设置,这其中包括相机和子相机以及子视口等等,得到后View会被销毁。

    参数

virtual void take (View &rhs)

    virtual bool readConfiguration (const std::string &filename)

    说明:该方法是从类osgViewer::ViewerBase中继承下来的方法,功能是读取一个配置文件来配置Viewer.现实中并不是常用读配置文件的方法来设置Viewer.如果读取成功,则返回True,返则返回假。

    参数

virtual bool readConfiguration (const std::string &filename)

    virtual bool isRealized () const

    说明:该方法是从类osgViewer::ViewerBase中继承下来的方法,功能是看Viewer是否已经执行了Realize操作,如果执行了则返回真,事则返回假。

    virtual void realize ()

    说明:该方法是从类osgViewer::ViewerBase中继承下来的方法,功能是该操作会使对Viewer之前的设置都使之生效。

    virtual void setStartTick (osg::Timer_t tick)

    说明:该方法是从类osgViewer::View中继承下来的方法,功能是设置时钟开始滴答点数,从那里开始计时。可以用于计算程序运行的时间等等。

    参数

virtual void setStartTick (osg::Timer_t tick)

    void setReferenceTime (double time=0.0)

    说明:设置参考时间,与上一个函数配合来使用。

    virtual void setSceneData (osg::Node *node)

    说明:设置场景中的数据,为场景中渲染的实际数据,在事面会讲解osg::Node类型。

    参数

OSG教程:场景保存类Viewer

    virtual GraphicsWindowEmbedded * setUpViewerAsEmbeddedInWindow (int x, int y, int width, int height)

    说明:该函数的功能是以嵌入式窗口的形式来设置该Viewer的渲染面。返回指向嵌入式界面指针。

    参数

OSG教程:场景保存类Viewer

    virtual double elapsedTime ()

    说明:该函数可以计算程序执行的时间,返回值为程序执行的时间,一般为毫秒级。

     virtual osg::FrameStamp * getViewerFrameStamp ()

    说明:这个函数返回当前Viewer的一个FrameStamp,至于什么是FrameStamp,大意是说规定两个时间,在此时间中规定帧的数目,在渲染时会按照这个帧数来把帧压在这个时间段当中。

     virtual int run () 说明:开始执行渲染操作,返回值一般为1。程序退出或出错时会返回0。

    virtual void advance (double simulationTime=USE_REFERENCE_TIME)

    说明:高级,表示从默认参考时间开始会计算一些信息,帧速,帧率,帧间隔等等。

     参数

    virtual void advance (double simulationTime=USE_REFERENCE_TIME)

    virtual void eventTraversal ()

    说明:事件遍历,遍历外部事件来处理场景中因事件发生而引起的渲染变化。

    virtual void updateTraversal ()

    说明:更新遍历,遍历更新场景的数据渲染。

    void setCameraWithFocus (osg::Camera *camera)

    说明:设置相机。

    参数

OSG教程:场景保存类Viewer

    osg::Camera * getCameraWithFocus () const osg::Camera * getCameraWithFocus () const

    说明:得到相机,返回值为一个相机。

    virtual void getCameras (Cameras &cameras, bool onlyActive=true)

    说明:得到相机群。参数一为引用类型,执行该函数后cameras就含有了Viewer的相机群。关于引用参数可以参考C++基本书籍。第二个参数问是否获得激活可用的相机群,而不可用的不获得,默认值为真。

    参数

virtual void getCameras (Cameras &cameras, bool onlyActive=true)

    virtual void getContexts (Contexts &contexts, bool onlyValid=true)

    说明:得到上下文,参数一为引用类型,执行该函数后contexts中就含有了Viewer的上下文,关于引用参数可以参考C++基本书籍。第二个参数问是否获得激活可用的上下文,而不可用的不获得,默认值为真。

    参数

OSG教程:场景保存类Viewer

    virtual void getWindows (Windows &windows, bool onlyValid=true)

    说明:得到Windows,这里的Windows并不能直接理解为所谓的窗口,应该理解为一个渲染面。执行该函数后windows中就含有了Viewer中的windows,关于引用参数可以参考C++基本书籍。第二个参数问是否获得激活可用的窗口,而不可用的不获得,默认值为真。

    参数

virtual void getWindows (Windows &windows, bool onlyValid=true)

    virtual void getAllThreads (Threads &threads, bool onlyActive=true)

    说明:得到所有当前Viewer中的线程,执行该函数后threads中会有该Viewer的线程,关于引用参数可以参考C++基本书籍。第二个参数问是否获得正在激活的线程,而不激活的线程不获得,默认值为真。

    参数

virtual void getAllThreads (Threads &threads, bool onlyActive=true)

    virtual void getOperationThreads (OperationThreads &threads, bool onlyActive=true)

    说明:得到操作线程[OperationThreads],执行该函数后threads中会有该Viewer的操作线程,关于引用参数可以参考C++基本书籍。第二个参数问是否获得正在激活的操作线程,而不激活的线程不获得,默认值为真。

    参数

virtual void getOperationThreads (OperationThreads &threads, bool onlyActive=true)

    virtual void getScenes (Scenes &scenes, bool onlyValid=true)

    说明:得到当前Viewer的Scenes, 执行该函数后scnes中会有该Viewer的scenes,关于引用参数可以参考C++基本书籍。第二个参数问是否获得可用的scenes,而不可用的scenes不获得,默认值为真。

    参数

virtual void getScenes (Scenes &scenes, bool onlyValid=true)

    virtual void getViews (Views &views, bool onlyValid=true)

    说明:得到当前Viewer的View,执行该函数后views中会有该Viewer的views,关于引用参数可以参考C++基本书籍。第二个参数问是否获得可用的views,而不可用的不获得,默认值为真。

    参数

virtual void getViews (Views &views, bool onlyValid=true)

    virtual void getUsage (osg::ApplicationUsage &usage) const

    说明:得到当前Viewer的命令行描述。

    参数

virtual void getUsage (osg::ApplicationUsage &usage) const

#include<osgViewer/Viewer> #include<osgViewer/ViewerEventHandlers> #include<osgGA/StateSetManipulator> #include<osg/Node> #include<osg/Geode> #include<osg/Geometry> #include<vector> #include<fstream> #include<iostream> #include<random> #include<osg/Group> #include<osg/MatrixTransform> using namespace std; struct P { //平面 int v1, v2, v3; //旧的,后面要改 }; vector<double> X, Y, Z, RAD; vector<P>PLANE; void readData(); //读原始数据 osg::ref_ptr<osg::Node> createTriangle(); //创建三角面 osg::ref_ptr<osg::Node> createTriangle2(); //创建三角面 class RotationCallback : public osg::NodeCallback { public: RotationCallback() : _angle(0.0) {} virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) { // 计算时间差 osg::Timer_t now = osg::Timer::instance()->tick(); double deltaTime = osg::Timer::instance()->delta_s(_lastTick, now); _lastTick = now; // 更新旋转角度 _angle += deltaTime * 10; // 调整旋转速度 // 限制角度在 [0, 2π) 范围内 if (_angle >= osg::PI * 2.0) { _angle -= osg::PI * 2.0; } // 创建旋转矩阵,指定旋转轴的位置 osg::Matrix rotationMatrix; rotationMatrix.makeRotate(_angle, osg::Vec3(0.0, 0.0, 1.0)); // 旋转角度围绕Z轴 osg::Matrix translateMatrix; translateMatrix.makeTranslate(0.1, 0.0, -0.01); // 平移旋转轴到左侧 osg::Matrix finalMatrix = translateMatrix * rotationMatrix; // 设置旋转变换节点的变换矩阵 dynamic_cast<osg::MatrixTransform*>(node)->setMatrix(finalMatrix); // 继续遍历子节点 traverse(node, nv); } protected: double _angle; osg::Timer_t _lastTick; }; struct CaptureCallback :public osg::Camera::DrawCallback { CaptureCallback(osg::ref_ptr<osg::Image> image) { image_ = image; } ~CaptureCallback() {} virtual void operator()(const osg::Camera& camera) const { //得到窗口系统接口 osg::ref_ptr<osg::GraphicsContext::WindowingSystemInterface> wsi = osg::GraphicsContext::getWindowingSystemInterface(); unsigned int width, height; //得到分辨率 wsi->getScreenResolution(osg::GraphicsContext::ScreenIdentifier(0), width, height); //分配一个image image_->allocateImage(width, height, 1, GL_RGB, GL_UNSIGNED_BYTE); //读取像素信息抓图 image_->readPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE); cout << 111 << endl; } private: osg::ref_ptr<osg::Image> image_; }; void main() { cout << "loading...\n"; readData(); cout << "OK\n"; osgViewer::Viewer viewer; // 观察器,用来查看模型 osg::Group* root = new osg::Group(); // 添加第一个模型 root->addChild(createTriangle().get()); // 创建第二个模型的旋转变换节点 osg::ref_ptr<osg::MatrixTransform> rotateTransform = new osg::MatrixTransform; rotateTransform->addChild(createTriangle2().get()); // 将旋转变换节点添加到根节点 root->addChild(rotateTransform.get()); // 附加回调到旋转变换节点 rotateTransform->setUpdateCallback(new RotationCallback); viewer.setSceneData(root); viewer.addEventHandler(new osgViewer::WindowSizeHandler); viewer.realize(); viewer.run(); } void readData() { fstream in("example.txt",ios::in); in.rdbuf()->pubsetbuf(0, 300*1024 * 1024); int cnt = 0; int N, E; in >> N >> E; for (int i = 0; i < N; i++) { double num; in >> num; X.push_back(num); } for (int i = 0; i < N; i++) { double num; in >> num; Y.push_back(num); } for (int i = 0; i < N; i++) { double num; in >> num; Z.push_back(num); } for (int i = 0; i < N; i++) { double num; in >> num; RAD.push_back(num); } for (int i = 0; i < E; i++) { int n1, n2, n3; in >> n1 >> n2 >> n3; PLANE.push_back({n1-1,n2-1,n3-1}); } in.close(); } osg::ref_ptr<osg::Node> createTriangle() { int numVertices = X.size(); // 获取顶点数量 int numFaces = PLANE.size(); // 获取面数量 // 创建顶点数组 osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array; for (int i = 0; i < numVertices; ++i) { vertices->push_back(osg::Vec3(X[i], Y[i], Z[i])); } // 创建几何体 osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry; geometry->setVertexArray(vertices.get()); // 计算并设置法线 osg::ref_ptr<osg::Vec3Array> normals = new osg::Vec3Array; normals->resize(numVertices, osg::Vec3(0.0f, 0.0f, 0.0f)); // 初始化法线为零向量 for (int i = 0; i < numFaces; ++i) { const P& plane = PLANE[i]; osg::Vec3 v1 = (*vertices)[plane.v1]; osg::Vec3 v2 = (*vertices)[plane.v2]; osg::Vec3 v3 = (*vertices)[plane.v3]; osg::Vec3 normal = (v2 - v1) ^ (v3 - v1); // 计算面的法线 // 将法线加到每个顶点上 (*normals)[plane.v1] += normal; (*normals)[plane.v2] += normal; (*normals)[plane.v3] += normal; } // 归一化法线 for (int i = 0; i < numVertices; ++i) { (*normals)[i].normalize(); } geometry->setNormalArray(normals.get()); geometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX); // 创建顶点索引数组 osg::ref_ptr<osg::DrawElementsUInt> indices = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES); for (int i = 0; i < numFaces; ++i) { if (Z[PLANE[i].v3] >= -0.568&& X[PLANE[i].v3]<=8) continue; const P& plane = PLANE[i]; indices->push_back(plane.v1); indices->push_back(plane.v2); indices->push_back(plane.v3); } geometry->addPrimitiveSet(indices.get()); // 设置几何体的颜色 osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array; colors->push_back(osg::Vec4(0.4f, 0.4f, 0.4f, 1.0f)); geometry->setColorArray(colors.get()); geometry->setColorBinding(osg::Geometry::BIND_OVERALL); // 设置几何体的渲染状态 osg::StateSet* stateset = geometry->getOrCreateStateSet(); //stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF); // 创建几何组结点 osg::ref_ptr<osg::Geode> geode = new osg::Geode; geode->addDrawable(geometry.get()); return geode.get(); } osg::ref_ptr<osg::Node> createTriangle2() { int numVertices = X.size(); // 获取顶点数量 int numFaces = PLANE.size(); // 获取面数量 // 创建顶点数组 osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array; for (int i = 0; i < numVertices; ++i) { vertices->push_back(osg::Vec3(X[i], Y[i], Z[i])); } // 创建几何体 osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry; geometry->setVertexArray(vertices.get()); // 计算并设置法线 osg::ref_ptr<osg::Vec3Array> normals = new osg::Vec3Array; normals->resize(numVertices, osg::Vec3(0.0f, 0.0f, 0.0f)); // 初始化法线为零向量 for (int i = 0; i < numFaces; ++i) { const P& plane = PLANE[i]; osg::Vec3 v1 = (*vertices)[plane.v1]; osg::Vec3 v2 = (*vertices)[plane.v2]; osg::Vec3 v3 = (*vertices)[plane.v3]; osg::Vec3 normal = (v2 - v1) ^ (v3 - v1); // 计算面的法线 // 将法线加到每个顶点上 (*normals)[plane.v1] += normal; (*normals)[plane.v2] += normal; (*normals)[plane.v3] += normal; } // 归一化法线 for (int i = 0; i < numVertices; ++i) { (*normals)[i].normalize(); } geometry->setNormalArray(normals.get()); geometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX); // 创建顶点索引数组 osg::ref_ptr<osg::DrawElementsUInt> indices = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES); for (int i = 0; i < numFaces; ++i) { if (Z[PLANE[i].v3] <= -0.568 || X[PLANE[i].v3] > 8) continue; const P& plane = PLANE[i]; indices->push_back(plane.v1); indices->push_back(plane.v2); indices->push_back(plane.v3); } geometry->addPrimitiveSet(indices.get()); // 设置几何体的颜色 osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array; colors->push_back(osg::Vec4(0.5f, 0.5f, 0.5f, 1.0f)); geometry->setColorArray(colors.get()); geometry->setColorBinding(osg::Geometry::BIND_OVERALL); // 设置几何体的渲染状态 osg::StateSet* stateset = geometry->getOrCreateStateSet(); //stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF); // 创建几何组结点 osg::ref_ptr<osg::Geode> geode = new osg::Geode; geode->addDrawable(geometry.get()); return geode.get(); } Camera::DrawCallback实现连续截图并导出图片
06-05
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值