前言
上章通过代码深入分析了前进到下一帧的详细过程。本章将继续分析帧循环过程中后续内容:事件处理与更新过程。
目录
- 1 事件处理
- 2 更新
1 事件处理
本节对参照用例(vulkanscenegraph显示倾斜模型-CSDN博客)中的如下代码进行深入探讨。
vsg_viewer->handleEvents();
void Viewer::handleEvents()
{
CPU_INSTRUMENTATION_L1_NC(instrumentation, "Viewer handle events", COLOR_UPDATE);
for (auto& vsg_event : _events)
{
for (auto& handler : _eventHandlers)
{
vsg_event->accept(*handler);
}
}
}
通过上章(vulkanscenegraph显示倾斜模型(6)-帧循环-CSDN博客),可知在前进到下一帧的阶段,通过轮询所有窗口的事件,获取所有窗口事件UIEvent对象,并将结果放置到_events(std::list<ref_ptr<UIEvent>>)变量中。
上述代码通过遍历所有窗口事件_events和事件处理器,使所有的事件在当前帧循环中得到处理。其中事件处理器存储在变量_eventHandlers(std::list<vsg::ref_ptr<vsg::Visitor>>)中,并通过vsg::Viewer封装的addEventHandler、addEventHandlers两个方法添加。
在5.4章( vulkanscenegraph显示倾斜模型(5.4)-相机操纵器-CSDN博客)介绍了vsg::Trackball相机操纵器,其本质是一种事件处理器,其通过重写vsg::Visitor的相关接口实现对鼠标输入等事件的处理,实现通过用户交互动态修改视图矩阵,从而改变模型在视口中的显示效果。
vsg_viewer->addEventHandler(vsg::CloseHandler::create(vsg_viewer));
vsg_viewer->addEventHandler(vsg::Trackball::create(vsg_camera));
如上为vulkanscenegraph显示倾斜模型示例代码(vulkanscenegraph显示倾斜模型-CSDN博客)中的122-124行代码,其除了添加一个vsg::Trackball事件处理器,还添加了一个vsg::CloseHandler事件处理器,本小节接下来将分析vsg::CloseHandler。
/// CloseHandler event handler used to respond to close events generated by a Window.
class CloseHandler : public Inherit<Visitor, CloseHandler>
{
public:
explicit CloseHandler(Viewer* viewer) :
_viewer(viewer) {}
KeySymbol closeKey = KEY_Escape; // KEY_Undefined
virtual void close()
{
// take a ref_ptr<> of the observer_ptr<> to be able to safely access it
ref_ptr<Viewer> viewer = _viewer;
if (viewer) viewer->close();
}
void apply(KeyPressEvent& keyPress) override
{
if (closeKey != KEY_Undefined && keyPress.keyBase == closeKey) close();
}
void apply(CloseWindowEvent&) override
{
close();
}
void apply(TerminateEvent&) override
{
close();
}
protected:
// use observer_ptr<> to avoid circular reference
observer_ptr<Viewer> _viewer;
};
VSG_type_name(vsg::CloseHandler);
} // namespace vsg
vsg::CloseHandler通过重写apply(KeyPressEvent& keyPress)、apply(CloseWindowEvent&)、apply(TerminateEvent&)方法,对KEY_Escape键盘消息、CloseWindowEvent与TerminateEvent事件响应,实现窗口的关闭。窗口的关闭调用vsg::Viewer的close方法:
void Viewer::close()
{
CPU_INSTRUMENTATION_L1_NC(instrumentation, "Viewer close", COLOR_VIEWER);
_close = true;
status->set(false);
stopThreading();
}
视景器的关闭,首先将标记_close置为true,将状态status置为false,接着停止视景器线程。
2 更新
本节对参照用例(vulkanscenegraph显示倾斜模型-CSDN博客)中的如下代码进行深入探讨。
vsg_viewer->update();
void Viewer::update()
{
CPU_INSTRUMENTATION_L1_NC(instrumentation, "Viewer update", COLOR_UPDATE);
// merge any updates from the DatabasePager
for (const auto& task : recordAndSubmitTasks)
{
if (task->databasePager)
{
CompileResult cr;
task->databasePager->updateSceneGraph(_frameStamp, cr);
if (cr.requiresViewerUpdate()) updateViewer(*this, cr);
}
}
// run update operations
updateOperations->run();
// run aniamtions
animationManager->run(_frameStamp);
}
上述代码包含三部分:场景树更新、更新操作、动画管理器运行。vulkanscenegraph显示倾斜模型过程中不涉及后两个过程,因此本章将重点深入分析场景树更新过程。
for (const auto& task : recordAndSubmitTasks)
{
if (task->databasePager)
{
CompileResult cr;
task->databasePager->updateSceneGraph(_frameStamp, cr);
if (cr.requiresViewerUpdate()) updateViewer(*this, cr);
}
}
以记录和提交的任务为粒度,调用vsg::DatabasePager的updateSceneGraph方法来更新场景树,并返回编译结果cr(CompileResult)值,接着根据返回的cr值调用updaetViewer方法更新视景器(注:vulkanscenegraph显示倾斜模型过程中不涉及)。后续章节将剖析vsg::DatabasePager在更新场景树过程中的作用。
文末:本章深入分析了帧循环中事件处理与更新两个关键处理流程,在事件处理过程中,通过给视景体添加事件处理器可实现事件的定制处理,其中vsg::Trackball为一种特殊的事件处理器,即相机操纵器,在更新过程中,主要为场景树的更新,后续将剖析vsg::DatabasePager在此过程中的核心作用。下章将分析帧循环中的记录与提交、呈现两个阶段。
待分析项:vsg::DatabasePager在更新场景树过程中的作用。