gldemo
|
本项目的主要任务是基于OpenGL和QT完成三维点云可视化漫游界面开发,进行漫游渲染器开发。即实现一个能完成三维模型加载、可视化交互、漫游订制功能的3D点云查看器。本项目可以应用于游戏开发、3D全景展示、VR全景直播、汽车模拟驾驶、三维设计软件的应用等多个领域。
软件的图形界面采用Qt Creatord搭建。主要包含6个部分:
菜单栏
文件打开、屏幕录制功能
工具栏
一共有四个工具。
场景树
用于显示当前3D场景中的各个节点。节点是以树形结构存储的,拖动节点并放到另一个节点之上可以调整节点的附属关系。右键单击节点可以添加或删除节点。
渲染界面
显示实时3D渲染结果。可以在图形界面内拖动鼠标或使用键盘快捷键调整摄像机视角。
节点基本属性编辑框
可以编辑当前选中节点的位移、旋转和缩放。
组件属性框
列出当前选中节点上所有组件(Component)的所有属性,可以双击编辑。
OpenGL提供了直接绘制图形的glBegin
、glVertex..
等函数,但是这些函数效率并不高,考虑到我们需要实时渲染十万量级以上的点云,且需要考虑相机、模型的运动,我们搭建了场景中模型的树形结构和配套的渲染管线。
渲染管线主要由Widget类进行调度。初始化过程中Widget类的实例会初始化OpenGL上下文、编译shader以及创建坐标轴等辅助线的渲染器。一个QTimer每20毫秒触发一次场景更新及重绘。
渲染时,从场景根节点开始,将其transform矩阵入栈,依次乘以子节点的transform矩阵,并递归渲染子节点。每个节点在渲染过程中会检查其上是否存在继承自Renderer类的组件,如果有就调用Renderer类的统一接口进行渲染。每一个Renderer的子类都会实现一套自身的渲染流程,目前一共实现了PointCloudRenderer,SkyboxRenderer和LineRenderer三种渲染器。这种物体-组件的设计使得我们能够很容易地扩展新的渲染器而不用对渲染管线的底层进行修改。
具体说明情参考技术细节中的点云渲染一节。
Qt提供了非常方便的信号槽机制。我们利用信号槽实现了渲染窗口和主窗口之间各种信号的同步。
信号槽的有两种方式,一种是在QtCreator中编辑,一种是在初始化时使用connect函数。
按钮回调函数
UI上的按钮被点击后,产生特定信号。使用QtCreator的信号槽编辑功能将这些信号连接到自定义的事件处理代码中。
物体选择信号
用户既可以在渲染窗口中使用鼠标左键选择物体,也可以在主窗口左侧的场景结构中选中物体节点。所以用户在渲染窗口中选择物体之后,会有一个信号发出,通知场景结构更新用户选取的物体,用户在场景结构中选择节点后,也会有一个信号发出,通知渲染窗口高亮选中的物体。
漫游录制信号
漫游录制的具体设定在一个新的弹出窗口中。用户确认设定之后,弹出窗口要通过信号槽通知主窗口用户进行了什么操作。主窗口则需要给渲染窗口发送信号实施对应的操作。当录制/保存完成后,渲染窗口还需要通知主窗口任务完成。具体信号流程情参考技术细节中的漫游录制一节。
如果对每个鼠标、键盘事件都分别监听,代码分散在不同的槽函数中,难以维护,且涉及到组合操作和拖动操作时需要设立大量成员变量来临时记录上一帧的输入值,很不方便。所以我们将所有用户输入放入静态的Input类进行统一的管理。每一次渲染更新之前Input类会将上一帧到这一帧的时间范围内记录到的所有事件都记录下来并放入缓存,同时开始接收新的输入事件。所有需要用到用户输入的代码逻辑都可以直接调用Input类的查询接口来获取当前帧发生的事件。