菜单
0 概述
1 和Qt结合
2 和Qt结合解决闪屏
3 插入一个小球
4 鼠标键盘交互

0 概述

当前文档描述的内容是将PE平台和Qt结合的例子,所有必须懂一点Qt相关的知识。关于PE的SDK熟不熟悉,不要紧,因为本文档就是讲述PE的SDK的。

1 和Qt结合

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函数,窗口中的内容会被重新绘制,导致会出现闪烁(看下面动态图)。

2 和Qt结合解决闪屏

解决闪屏问题,代码如下:

setAttribute(Qt::WA_PaintOnScreen);

QPaintEngine *MainWindow::paintEngine() const
{
  return nullptr;
}
注意:如果我们重写paintEvent,是没有办法解决闪屏的问题。

代码例子在SandSculpture/002WithQtTwinkle目录下

上述代码,并没有完美解决闪屏问题,当我们多次缩放窗口时,会出现窗口刷新不完全的问题,如下图所示。

3 在场景中添加小球

在实现“三维场景中添加一个小球”功能之前,我们需要先了解一下基础的三维概念。

可以这样简单理解,在三维世界中,有一个摄像机,相当于人眼,人眼看到的东西(摄像机拍摄的内容)就是计算机屏幕上显示的东西。

关于摄像机的详细概念,可以在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目录下

效果图如下:

4 鼠标键盘交互

鼠标和键盘的交互,是一个相对复杂功能,我们要把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目录下

鼠标交互效果图如下。