• 场景图形管理-多视图与相机(3)


            在OSG中多视图的管理是通过osgViewer::CompositeViewer类来实现的。该类负责多个视图的管理及同步工作,继承自osgViewer;:ViewerBase类,继承关系图如图8-13所示

    图8-13 osgViewer::CompositeViewer 的继承关系图

            在前面已经讲到,osgViewer:ViewerBase 类主要负责线程管理设置线程模式启动线程等工作在多视图渲染时,线程管理一直都是一个令人非常头痛的问题,但这些底层工作在 osgViewer::CompositeViewer类中已经实现了。如果读者想了解得更详细,可参看osgViewer/CompositeViewer.cpp源代码。

            对于osgViewer::CompositeViewer,它内部已经包含了多个视图(osg::View),使用它来表示一个视图当然是可以的,此时osgViewer:CompositeViewer 的作用与标准的osgViewer::Viewer 对象并无太大差别,但是比起每次只管理一个视图的情形来说,管理和使用多个视图还是显得略微麻烦。因此,建议在只有一个视图时尽量选择使用 osgViewer::Viewer。当然,有时可能需要用到不止一个视图,也可能在多个视口内显示同一视图的内容(如多数 CAD 软件),或同时显示一个3D场景和一幅小地图视图,或读取多个模型文件并分别独立地进行控制。对于这些程序来说,往往需要在一个或多个场景(osgVicwer:Scene)上管理多个视图(osgView)此时程序的管理方式要比单独的osgViewer.:Viewer情形下复杂得多。事实上,程序的细节程度总是与问题的复杂程度成比例的,因此,我们有必要在正确的条件下选择正确的实现方式。

            在osgViewer:CompositeViewer中添加视图或移除视图可以用下面的成员函数:

    1. void addView(osgViewer.:View*view)//添加一个视图
    2. void removeView(osgViewer::View*view)//移除一个视图
    3. osgViewer::View *getView(unsigned i) //得到视图的索引
    4. const osgViewer::View *getView(unsigned i)const//得到视图的索引
    5. unsigned int getNumViews() const//得到视图的个数

            在论坛上,有很多人会提问如何来做一个“鹰眼”,其实,这是比较简单的实现。用osgViewer.:CompositeViewer类实现多视图管理,让一个小地图HUD显示一个视图,另一个视图染主窗口即可。本书并没有专门提供一个相关的例子,读者可以通过修改本书的例子来自行完成

    1. 多视图相机渲染示例

            多视图相机渲染示例的代码如程序清单8-5所示

    1. // 多视图相机渲染示例
    2. void compositeViewer_8_5(const string &strDataFolder)
    3. {
    4. // 创建CompositeViewer对象
    5. osg::ref_ptr viewer = new osgViewer::CompositeViewer();
    6. // 获取牛的模型
    7. string strDataPath = strDataFolder + "cow.osg";
    8. osg::ref_ptr cow = osgDB::readNodeFile(strDataPath);
    9. // 读取飞机模型
    10. strDataPath = strDataFolder + "cessna.osg";
    11. osg::ref_ptr cessna = osgDB::readNodeFile(strDataPath);
    12. // 优化场景数据
    13. osgUtil::Optimizer optimizer;
    14. optimizer.optimize(cow.get());
    15. optimizer.optimize(cessna.get());
    16. // 设置图形环境特性
    17. osg::ref_ptr traits = new osg::GraphicsContext::Traits();
    18. traits->x = 100;
    19. traits->y = 100;
    20. traits->width = 900;
    21. traits->height = 700;
    22. traits->windowDecoration = true;
    23. traits->doubleBuffer = true;
    24. traits->sharedContext = 0;
    25. // 创建图形环境特性
    26. osg::ref_ptr gc = osg::GraphicsContext::createGraphicsContext(traits.get());
    27. if (gc->valid())
    28. {
    29. osg::notify(osg::INFO) << " GraphicsWIndow has been created successfully." << endl;
    30. // 清除窗口颜色及颜色和深度缓冲
    31. gc->setClearColor(osg::Vec4f(0.2f, 0.2f, 0.6f, 1.0f));
    32. gc->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    33. }
    34. else
    35. {
    36. osg::notify(osg::NOTICE) << " GrraphicsWidnow has not been created successfully." << endl;
    37. }
    38. //视图1
    39. {
    40. // 创建视图1
    41. osg::ref_ptr view = new osgViewer::View;
    42. viewer->addView(view.get());
    43. // 设置视图场景数据
    44. view->setSceneData(cow.get());
    45. // 设置相机视口及图形环境
    46. view->getCamera()->setViewport(new osg::Viewport(0, 0, traits->width / 2, traits->height / 2));
    47. view->getCamera()->setGraphicsContext(gc.get());
    48. // 设置操作器
    49. view->setCameraManipulator(new osgGA::TrackballManipulator);
    50. // 添加事件处理
    51. view->addEventHandler(new osgViewer::StatsHandler);
    52. view->addEventHandler(new osgViewer::WindowSizeHandler);
    53. view->addEventHandler(new osgViewer::ThreadingHandler);
    54. view->addEventHandler(new osgViewer::RecordCameraPathHandler);
    55. }
    56. // 视图2
    57. {
    58. osg::ref_ptr view = new osgViewer::Viewer;
    59. viewer->addView(view.get());
    60. view->setSceneData(cessna.get());
    61. view->getCamera()->setViewport(new osg::Viewport(traits->width / 2, 0, traits->width / 2, traits->height / 2));
    62. view->getCamera()->setGraphicsContext(gc.get());
    63. view->setCameraManipulator(new osgGA::TrackballManipulator);
    64. }
    65. // 视图3
    66. {
    67. osg::ref_ptr view = new osgViewer::View;
    68. viewer->addView(view.get());
    69. view->setSceneData(cessna.get());
    70. // 根据分辨率确定合适的投影来保证显示的图形不变形
    71. double fovy, aspectRatio, zNear, zFar;
    72. view->getCamera()->getProjectionMatrixAsPerspective(fovy, aspectRatio, zNear, zFar);
    73. double newAspectRatio = double(traits->width) / double(traits->height/2);
    74. double aspectRaitoChange = newAspectRatio / aspectRatio;
    75. if (aspectRaitoChange != 1.0)
    76. {
    77. view->getCamera()->getProjectionMatrix() *= osg::Matrix::scale(1.0 / aspectRaitoChange, 1.0, 1.0);
    78. }
    79. view->getCamera()->setViewport(new osg::Viewport(0, traits->height / 2, traits->width, traits->height / 2));
    80. view->getCamera()->setGraphicsContext(gc.get());
    81. view->setCameraManipulator(new osgGA::TrackballManipulator);
    82. }
    83. viewer->realize();
    84. viewer->run();
    85. }

            运行程序,截图如图8-14所示

    图8-14多视图相机渲染示例截图

  • 相关阅读:
    我说ArrayList初始容量是10,面试官让我回去等通知
    基于ssm的视力保养连锁预约系统设计与实现-计算机毕业设计源码+LW文档
    最全分布式面试题整理
    centos7安装php
    C语言的三个经典题目:三步翻转法、杨氏矩阵、辗转相除法
    HTML期末学生大作业:基于html+css+javascript+jquery企业餐厅11页 企业网站制作
    在Winform分页控件中集成导出PDF文档的功能
    linux服务器在没有网的条件下,怎么安装使用numpy呢
    git cherry-pick 合并某次提交
    Spark SQL
  • 原文地址:https://blog.csdn.net/liangfei868/article/details/134439061