第二日(四)osgViewer::Viewer::setCameraFocus()

本文深入剖析了OSGViewer框架的内部工作流程,包括帧事件的创建、漫游器初始化、图形上下文的实现等关键步骤。通过逐层分解,揭示了从事件处理到渲染的全过程。

目前的框架如下:

osgViewer::viewBase:: frame()

{

viewerInit();[

                          //创建帧事件,并将漫游器与事件和视口相关联

                            ->   osgViewer::Viewer::ViewerInit()

                           ->  osgViewer::View::Init();

                          ->(1)osgGA::EventQueue::createEvent();

                            (2)osgGA::MatrixManipulator::Init();

                            ->(2.1)各种漫游器::init()

                 ]

isRealized();[

                                    //获取图形上下文数组。再遍历上下文数组,只要有一个准备好就Ok

                                  ->   osgViewer::Viewer::isRealized();

                                 ->(1)osgViewer::Viewer::getContexts().

                                          ->(1.1)osg::camera::getGraphicsContext()

                                          ->(1.2)osg::View::getNumSlaves()

                                         ->(1.3)osg::View::getSlave()

                                         ->(1.4)LessGraphicsContext()->osg::GraphicContext::getTraits()

                                ->(2)osg::GraphicContext::isRealized()

                                        ->(2.1)->(1)

                                       ->(2.2)osg::GraphicsContext::isRealized()

                                                ->osg::GraphicsContext::isRealizedImplementation()

                                               ->(2.2.1)osgViewer::GraphicsWindow::isRealizedImplementation()

                                                             ->(2.2.1.1)osgViewer:: GraphicsWindowWin32 ::isRealizedImplementation()

                                                             ->(2.2.1.2) osgViewer::GraphicsWindowEmbedded ::isRealizedImplementation()

                                              ->(2.2.2)osgViewer::PixelBufferWin32::isRealizedImplementation()

                               -

 

                    ]

realize();

advance(simulationTime);

eventTraversal();

updateTraversal();

renderingTraversals();

}

 下一步,很明显要进行realize()了,但是太长,所以要改变从外到内的方式,而是一个函数一个函数地分析,最后汇总意说了些啥。

 

第一个函数是 setCameraWithFocus(0);

顾名思义,就是将焦点窗口设为NULL,即没有焦点窗口。

 

对于单窗口来说,很简单一句话


        void setCameraWithFocus(osg::Camera* camera) { _cameraWithFocus = camera; }

对于多个视口类来说,还要判断,如果这个摄像机不为空,哪个视口为焦点视口。
bool osgViewer::View::containsCamera(const osg::Camera* camera) const,

判断方法也简单,就是对于这个视图,主从相机的指针是不是包含这个camera,

 

当然,还是以单窗口为例

 

目前的框架如下:

osgViewer::viewBase:: frame()

{

viewerInit();[

                          //创建帧事件,并将漫游器与事件和视口相关联

                            ->   osgViewer::Viewer::ViewerInit()

                           ->  osgViewer::View::Init();

                          ->(1)osgGA::EventQueue::createEvent();

                            (2)osgGA::MatrixManipulator::Init();

                            ->(2.1)各种漫游器::init()

                 ]

isRealized();[

                                    //获取图形上下文数组。再遍历上下文数组,只要有一个准备好就Ok

                                  ->   osgViewer::Viewer::isRealized();

                                 ->(1)osgViewer::Viewer::getContexts().

                                          ->(1.1)osg::camera::getGraphicsContext()

                                          ->(1.2)osg::View::getNumSlaves()

                                         ->(1.3)osg::View::getSlave()

                                         ->(1.4)LessGraphicsContext()->osg::GraphicContext::getTraits()

                                ->(2)osg::GraphicContext::isRealized()

                                        ->(2.1)->(1)

                                       ->(2.2)osg::GraphicsContext::isRealized()

                                                ->osg::GraphicsContext::isRealizedImplementation()

                                               ->(2.2.1)osgViewer::GraphicsWindow::isRealizedImplementation()

                                                             ->(2.2.1.1)osgViewer:: GraphicsWindowWin32 ::isRealizedImplementation()

                                                             ->(2.2.1.2) osgViewer::GraphicsWindowEmbedded ::isRealizedImplementation()

                                              ->(2.2.2)osgViewer::PixelBufferWin32::isRealizedImplementation()

                               -

 

                    ]

realize(); [

                    //建立视口和相关的线程

                     ->osgViewer::Viewer::realize()

                     ->(1) osgViewer::Viewer::setCameraWithFocus()

                     ->(2)osgViewer::Viewer::getContexts()

                    ->(3)待续

                ]

advance(simulationTime);

eventTraversal();

updateTraversal();

renderingTraversals();

}

在OpenSceneGraph(OSG)中,`osgViewer::Viewer` 默认以阻塞模式运行,即进入事件循环后持续渲染,直到窗口关闭。若需实现**不阻塞显示**(即非阻塞渲染),通常需结合多线程或异步机制,避免主线程被渲染循环占用。以下是几种实现方式: --- ### **方法1:使用 `setRunFrameScheme` 控制帧循环** 通过设置 `Viewer` 的运行模式为 `ON_DEMAND`,仅在需要时(如事件触发或手动调用)渲染帧,避免持续阻塞: ```cpp #include <osgViewer/Viewer> int main() { osgViewer::Viewer viewer; viewer.setSceneData(/* 你的场景数据 */); // 设置为按需渲染模式(非阻塞) viewer.setRunFrameScheme(osgViewer::ViewerBase::ON_DEMAND); // 启动渲染线程(非阻塞) viewer.realize(); // 主线程继续执行其他任务 while (!viewer.done()) { // 手动触发渲染(可选) viewer.frame(); // 其他逻辑... std::this_thread::sleep_for(std::chrono::milliseconds(16)); // 模拟其他工作 } return 0; } ``` --- ### **方法2:多线程分离渲染与逻辑** 将 `Viewer` 放在单独线程中运行,主线程保持响应: ```cpp #include <osgViewer/Viewer> #include <thread> void renderThread() { osgViewer::Viewer viewer; viewer.setSceneData(/* 你的场景数据 */); viewer.run(); // 阻塞,但运行在独立线程中 } int main() { // 启动渲染线程 std::thread thread(renderThread); thread.detach(); // 分离线程,避免阻塞主线程 // 主线程继续执行其他任务 while (true) { // 其他逻辑... } return 0; } ``` --- ### **方法3:使用 `osgViewer::CompositeViewer`** 通过 `CompositeViewer` 管理多个视图,结合事件循环的异步处理: ```cpp #include <osgViewer/CompositeViewer> int main() { osgViewer::CompositeViewer viewer; // 添加多个视图(可选) auto view1 = new osgViewer::View; view1->setSceneData(/* 场景1 */); viewer.addView(view1); // 设置为非阻塞模式 viewer.setRunFrameScheme(osgViewer::ViewerBase::ON_DEMAND); // 主线程中手动控制渲染 while (!viewer.done()) { viewer.frame(); // 其他任务... } return 0; } ``` --- ### **关键点总结** 1. **`ON_DEMAND` 模式**:避免自动连续渲染,需手动调用 `frame()`。 2. **多线程分离**:将渲染放在独立线程,主线程不受影响。 3. **事件处理**:确保 `Viewer` 的事件队列仍能接收输入(如需交互)。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值