近期用了款叫DesktopSpace,也想实现一下这款软件实现的效果
具体实现步骤:
- 使用Qt3D绘制个旋转的立方体(一)
- 使用快捷键控制立方体显示面(二)
- 创建6个人虚拟桌面,截取不同虚拟桌面,显示在不同的面上 (三)
- 在立方体上播放视频
首先用Qt3D绘制一下桌面截图旋转的效果
Qt3D简单介绍
Qt 3D 是一个用于创建交互式 3D 图形应用程序的框架。它提供了一组类和函数,用于创建、渲染和操作 3D 场景。Qt 3D 在 Qt c++ 和 Qt Quick 应用程序中支持 2D 和 3D 渲染,为近实时仿真系统提供了功能。
以下是 Qt 3D 中一些常用的类说明和代码流程:
Qt3DCore:这是 Qt 3D 框架的核心模块,包含了一些基本类和接口,用于构建 3D 场景和实体。其中一些重要的类包括:
QEntity:表示 3D 场景中的实体,可以添加组件和子实体。
QTransform:表示实体的变换信息,用于控制实体的位置、旋转和缩放等属性。
Qt3DRender:这个模块主要用于渲染图形对象,包括定义材质、纹理和着色器等。其中一些重要的类包括:
QMaterial:表示实体的材质,包含了表面属性、纹理和渲染状态等。
QEffect:定义了渲染效果的着色器程序。
QTexture:表示纹理,可以加载图像并应用于材质。
Qt3DInput:这个模块用于处理用户输入(例如鼠标和键盘事件),以及与用户交互的功能。其中一些重要的类包括:
QMouseDevice:用于监听和处理鼠标事件。
QKeyboardDevice:用于监听和处理键盘事件。
下面是一个简单的 Qt 3 D 代码流程示例,展示了如何创建一个带有实体、材质和变换的场景:
#include <Qt3DCore/QEntity>
#include <Qt3DRender/QMaterial>
#include <Qt3DRender/QEffect>
#include <Qt3DRender/QTexture>
#include <Qt3DCore/QTransform>
int main(int argc, char** argv) {
QApplication app(argc, argv);
// 创建场景根实体
Qt3DCore::QEntity sceneRoot;
// 创建一个实体
Qt3DCore::QEntity* entity = new Qt3DCore::QEntity(&sceneRoot);
// 创建材质
Qt3DRender::QMaterial* material = new Qt3DRender::QMaterial(entity);
// 创建纹理
Qt3DRender::QTexture2D* texture = new Qt3DRender::QTexture2D(material);
// 设置纹理属性
// 创建效果
Qt3DRender::QEffect* effect = new Qt3DRender::QEffect();
// ...
}
这个示例只是 Qt 3 D 的一个简单应用,如果需要更深入了解和使用 Qt 3 D ,建议阅读官方文档和相关教程。
绘制旋转立方体
主函数
#include "cubewidget.h"
#include <Qt3DExtras/QTextureMaterial>
#include <QImage>
#include <QApplication>
#include <QWidget>
#include <QHBoxLayout>
#include <QLabel>
#include <QCheckBox>
#include <Qt3DCore/QEntity>
#include <Qt3DCore/QTransform>
#include <Qt3DExtras/QCuboidMesh>
#include <Qt3DExtras/QPhongMaterial>
#include <Qt3DExtras/Qt3DWindow>
#include <Qt3DExtras/QOrbitCameraController>
#include <Qt3DExtras/QForwardRenderer>
#include <QTimer>
#include <Qt3DRender/QCamera>
#include <Qt3DCore/QComponent>
#include <Qt3DRender/QTextureImage>
#include <Qt3DRender/QTexture>
#include <QMatrix3x3>
#include <QRenderSurfaceSelector>
#include <QImage>
#include "rotatorutil.h"
#include "rotator.h"
#include "hotkeymanager.h"
#include "mymaterialimage.h"
#include "lazyutil.h"
#include "animationutil.h"
CubeWidget::CubeWidget(QWidget *parent)
: QWidget{parent}
{
// 创建3D窗口
Qt3DExtras::Qt3DWindow *view = new Qt3DExtras::Qt3DWindow();
view->defaultFrameGraph()->setClearColor(QColor(210, 210, 220, 0));
view->setTitle("Qt3D C++ example: rotate cube");
// 创建一个容器小部件和窗口布局
QWidget *container = QWidget::createWindowContainer(view);
container->setAttribute(Qt::WA_TranslucentBackground, true);
QHBoxLayout *layout = new QHBoxLayout();
layout->addWidget(container, 1);
// 创建一个用于窗口的小部件并设置其布局
setLayout(layout);
// 创建场景的根实体
Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity();
// 创建相机实体并设置其位置和视图中心
Qt3DRender::QCamera *cameraEntity = view->camera();
cameraEntity->setPosition(QVector3D(10.0f, 0, 0.0f));
cameraEntity->setViewCenter(QVector3D(0, 0, 0));
// 创建立方体实体并添加立方体网格组件和冯氏材质组件
Qt3DCore::QEntity *cubeEntity = new Qt3DCore::QEntity(rootEntity);
Qt3DExtras::QCuboidMesh *cubeMesh = new Qt3DExtras::QCuboidMesh();
cubeMesh->setXExtent(5.1f);
cubeMesh->setYExtent(3.23f);
cubeMesh->setZExtent(5.1f);
// cubeMesh->setXYMeshResolution(QSize(300, 100));
// cubeMesh->setXZMeshResolution(QSize(300, 100));
// cubeMesh->setYZMeshResolution(QSize(100, 100));
auto *image = new MyQPaintedTextureImage;
image->setImage(LazyUtil::Instance()->grabScreenImage());
auto *cubeMaterial = new Qt3DExtras::QTextureMaterial;
cubeMaterial->texture()->addTextureImage(image);
#ifdef USE_OCV
QTimer* timer = new QTimer(this);
connect(timer, &QTimer::timeout, image, &MyQPaintedTextureImage::updateImage);
timer->start(50); // 1000毫秒刷新一次
#endif
// 将立方体网格组件和冯氏材质组件添加到立方体实体
cubeEntity->addComponent(cubeMesh);
cubeEntity->addComponent(cubeMaterial);
// 创建一个变换组件并将其添加到立方体实体
Qt3DCore::QTransform *transform = new Qt3DCore::QTransform();
cubeEntity->addComponent(transform);
#if 1
// 定时旋转
Rotator *rotator = new Rotator();
QObject::connect(rotator, &Rotator::rotationChanged, transform, &Qt3DCore::QTransform::setRotation);
#else
// 快捷键旋转
RotatorUtil *rotator = new RotatorUtil();
QObject::connect(rotator, &RotatorUtil::rotationChanged, transform, &Qt3DCore::QTransform::setRotation);
QObject::connect(HotkeyManager::Instance(), &HotkeyManager::angleHorizontalChanged, rotator, &RotatorUtil::updateAngleHorizontal);
HotkeyManager::Instance()->registerLeftRotateHotkey(rotator);
HotkeyManager::Instance()->registerRightRotateHotkey(rotator);
QObject::connect(HotkeyManager::Instance(), &HotkeyManager::angleVerticalChanged, rotator, &RotatorUtil::updateAngleVertical);
HotkeyManager::Instance()->registerTopRotateHotkey(rotator);
HotkeyManager::Instance()->registerBottomRotateHotkey(rotator);
QObject::connect(HotkeyManager::Instance()->getWorker(), &RotateWorker::angleHorizontalChanged, rotator, &RotatorUtil::updateAngleHorizontal);
QObject::connect(HotkeyManager::Instance()->getWorker(), &RotateWorker::angleVerticalChanged, rotator, &RotatorUtil::updateAngleVertical);
#endif
// 设置窗口的根实体
view->setRootEntity(rootEntity);
setAttribute(Qt::WA_TranslucentBackground, true);
AnimationUtil::AnimationSmaller(this);
}
动画控制类
#ifndef ROTATOR_H
#define ROTATOR_H
#include <Qt3DCore/QComponent>
#include <QTimer>
#include <QVector3D>
#include <QQuaternion>
// A custom component that controls the rotation of an entity
class Rotator : public Qt3DCore::QComponent
{
Q_OBJECT
public:
Rotator(Qt3DCore::QNode *parent = nullptr)
: Qt3DCore::QComponent(parent)
, m_angle(0.0f)
{
// Create a timer to update the angle every 10 ms
QTimer* timer=new QTimer(this);
connect(timer, &QTimer::timeout, this, &Rotator::updateAngle);
timer->start(10);
}
// A function to get the current rotation as a quaternion
QQuaternion rotation() const
{
// Calculate the rotation axis as the cross product of the up vector and the forward vector
QVector3D axis = QVector3D(0.0f, 1.0f, 0.0f)
.crossProduct(QVector3D(0.0f, -1.0f, 0.0f),
QVector3D(-1.0f, 0.0f, 1.0f));
// Normalize the axis
axis.normalize();
// Return the rotation as a quaternion
return QQuaternion::fromAxisAndAngle(axis, m_angle);
}
private slots:
// A slot to update the angle by 1 degree
void updateAngle()
{
// Increment the angle by 1 degree
m_angle += 0.2f;
// Wrap the angle to [0, 360) range
if (m_angle >= 360.0f) {
m_angle -= 360.0f;
}
// Emit a signal to notify the change of rotation
emit rotationChanged(rotation());
}
signals:
void rotationChanged(const QQuaternion &rotation);
private:
float m_angle; // The angle of rotation in degrees
};
#endif // ROTATOR_H