当前文档描述的内容是将PE平台和Qt结合的例子,所有必须懂一点Qt相关的知识。关于PE的SDK熟不熟悉,不要紧,因为本文档就是讲述PE的SDK的。
PE平台的sdk显示在Qt窗口,仅需要行代码即可,代码如下:
#include "VsView.h"
HWND hwnd = (HWND)this->centralWidget()->winId();
VsInital(hwnd); //没有这句,直接崩溃
view = new CVsView(hwnd);
mTimer.setInterval(40);
mTimer.start();
connect(&mTimer, &QTimer::timeout, this, [=](){
DWORD t = VsGetTickCount();
view->m_tEventMgr.Tick(t);
});
代码例子在SandSculpture/001WithQt目录下
运行效果图如下:
由于Qt的绘制事件,会在窗口大小改变、显示隐藏、聚焦等情况下,会重新调用paintEvent函数,窗口中的内容会被重新绘制,导致会出现闪烁(看下面动态图)。
解决闪屏问题,代码如下:
setAttribute(Qt::WA_PaintOnScreen);
QPaintEngine *MainWindow::paintEngine() const
{
return nullptr;
}
代码例子在SandSculpture/002WithQtTwinkle目录下
上述代码,并没有完美解决闪屏问题,当我们多次缩放窗口时,会出现窗口刷新不完全的问题,如下图所示。
在实现“三维场景中添加一个小球”功能之前,我们需要先了解一下基础的三维概念。
可以这样简单理解,在三维世界中,有一个摄像机,相当于人眼,人眼看到的东西(摄像机拍摄的内容)就是计算机屏幕上显示的东西。
关于摄像机的详细概念,可以在opengl中文教程中查看 (这个教程是opengl的入门教程,但是三维本来就是一个门槛很高领域,所以初学者看入门教程也会觉得很难)
摄像机有3个参数,分别是:位置、上向量、右向量、目标位置和远近点。看下图解释这四个参数。
个人理解,近平面和远平面之间的物体,就是显示在计算机屏幕上的。
在三维场景中插入小球代码如下:
// 设置相机
float eye[] = {0, 20, -20}; // 摄像机位置
float tar[] = {0, 0, 0}; // 目标位置
float up[] = {0, 1, 0}; // 上向量
VsSetCamera(eye, tar, up);
VsSetNearFar(0.1f, 10000.f, NULL); // 设置远近平面
// 基本几何体
VsOpenField("/scene/model/ball");
VsSetMaterialDiffuse(1, 0, 0);
VsInsertSphere(0, 1, 0, 1); // 插入小球
VsInsertSphere(-5, 1, 0, 1);// 插入小球
VsInsertSphere(5, 1, 0, 1); // 插入小球
VsCloseField();
VsInvalidate();
代码例子在SandSculpture/003AddBall目录下
效果图如下:
鼠标和键盘的交互,是一个相对复杂功能,我们要把Qt窗口的鼠标和键盘事件全部重写一遍,在重写在鼠标和键盘事件函数中,再调用平台sdk相关函数。
关于鼠标和键盘交互的代码,相对复杂,很难用语言描述,小伙伴直接去看代码。下面列举一下需要重写函数:
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void mouseDoubleClickEvent(QMouseEvent *event) override;
void wheelEvent(QWheelEvent *event) override;
void keyPressEvent(QKeyEvent *event) override;
void keyReleaseEvent(QKeyEvent *event) override;
void contextMenuEvent(QContextMenuEvent *event) override;
代码例子在SandSculpture/004MouseKeyboardInteraction目录下
鼠标交互效果图如下。