嵌入式系统大作业——基于QT的3D模型展示

  • 写在前面
  • 实验设备
  • 实现内容
  • 实现过程
    • 在win10上利用SolidWorks软件对模型进行预处理:
    • 编写代码实现功能:
  • 效果演示
  • 参考资料

写在前面

该大作业是本博主研究生课程所需,结合自身数字孪生方向,在Ubuntu中利用QT实现3D模型的展示,主要功能有3D模型的旋转、放缩、移动和灯光渲染位置的调整。

该文章文末会附上实现代码以及演示视频。编写不易,若有帮助请点赞关注收藏,谢谢!

实验设备

硬件:

电脑 (主频2.8GHz,内存24GB)

软件:

Windows 10 家庭中文版

VMware 16

Ubuntu 22.04.1

SolidWorks 2022

实现内容

在Linux中利用QT设计一款可以显示3D模型的界面,并通过浏览本地文件夹打开指定的3D模型。可以通过键盘对模型进行操作,实现模型的平移、旋转、缩放这三大基本功能,并且可以通过改变灯光位置,在不同角度对模型进行渲染展示。

实现过程

在win10上利用SolidWorks软件对模型进行预处理:

建议将模型转换为.OBJ格式,.OBJ文件是一种文本文件,可以直接用写字板打开进行查看和编辑修改,因此在Linux中更好读取与展示。由于原模型文件太大,在转换时还需要进行简化处理。

编写代码实现功能:

  1. 编写QT界面程序modelviewer.cpp:
 #include "modelviewer.h"#include "ui_modelviewer.h"#include "scene.h"ModelViewer::ModelViewer(QWidget *parent) :QMainWindow (parent),ui(new Ui::ModelViewer){ui->setupUi(this);setFocusPolicy(Qt::TabFocus);//central widgetQWidget *central = new QWidget();setCentralWidget(central);//sceneQt3DExtras::Qt3DWindow *view = new Qt3DExtras::Qt3DWindow();QWidget *sceneWidget = QWidget::createWindowContainer(view);scene = new Scene(view);view-> installEventFilter(this);//sliderQSlider *xSlider = createSlider();QSlider *ySlider = createSlider();QSlider *zSlider = createSlider();zSlider->setValue(-1);connect(xSlider,&QSlider::valueChanged,scene,&Scene::LightXChanged);connect(ySlider,&QSlider::valueChanged,scene,&Scene::LightYChanged);connect(zSlider,&QSlider::valueChanged,scene,&Scene::LightZChanged);//layoutQLabel *xLabel = new QLabel();QLabel *yLabel = new QLabel();QLabel *zLabel = new QLabel();xLabel->setText("X");yLabel->setText("Y");zLabel->setText("Z");QVBoxLayout *xLayout = new QVBoxLayout;QVBoxLayout *yLayout = new QVBoxLayout;QVBoxLayout *zLayout = new QVBoxLayout;xLayout->addWidget(xSlider);xLayout->addWidget(xLabel);yLayout->addWidget(ySlider);yLayout->addWidget(yLabel);zLayout->addWidget(zSlider);zLayout->addWidget(zLabel);QWidget *xWidget = new QWidget();QWidget *yWidget = new QWidget();QWidget *zWidget = new QWidget();xWidget->setLayout(xLayout);yWidget->setLayout(yLayout);zWidget->setLayout(zLayout);xWidget->setFixedWidth(50);yWidget->setFixedWidth(50);zWidget->setFixedWidth(50);QHBoxLayout *sceneLayout = new QHBoxLayout;sceneLayout->addWidget(sceneWidget);sceneLayout->addWidget(xWidget);sceneLayout->addWidget(yWidget);sceneLayout->addWidget(zWidget);QWidget *mainWidget = new QWidget();mainWidget->setLayout(sceneLayout);QLabel *controlDescription = new QLabel();controlDescription->setStyleSheet("font: 12pt;");controlDescription->setText("File->Open 打开一个3D模型文件. \n""利用方向键可平移模型. \n""利用shift + 方向键可缩放模型. \n""利用ctrl + 方向键可旋转模型. \n""利用右侧的滑块可调整灯光位置.");QVBoxLayout *topLayout = new QVBoxLayout;topLayout->addWidget(mainWidget);topLayout->addWidget(controlDescription);central->setLayout(topLayout);}QSlider *ModelViewer::createSlider(){QSlider *slider = new QSlider(Qt::Vertical);slider->setRange(-180, 180);slider->setSingleStep(1);slider->setPageStep(15);slider->setTickInterval(15);slider->setTickPosition(QSlider::TicksRight);return slider;}ModelViewer::~ModelViewer(){delete ui;}bool ModelViewer::eventFilter(QObject *obj, QEvent *event){if (event->type() == QEvent::KeyPress){QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);scene->KeyControls(keyEvent);}return QObject::eventFilter(obj, event);}void ModelViewer::on_actionOpen_File_triggered(){QString filename= QFileDialog::getOpenFileName(this,"Open file");QFile file(filename);currentFile = filename;if (!file.open(QIODevice::ReadOnly)) {QMessageBox::warning(this,"Warning", "Cannot open "+file.errorString());}setWindowTitle(filename);Qt3DRender::QMesh *mesh = new Qt3DRender::QMesh();QUrl data =QUrl::fromLocalFile(filename);mesh->setSource(data);scene->NewScene(mesh);}

2.编写界面程序头文件modelviewer.h:

 #ifndef MODELVIEWER_H#define MODELVIEWER_H#include <QMainWindow>#include <Qt3DCore/QEntity>#include <Qt3DWindow>#include <QKeyEvent>#include <QFile>#include <QFileDialog>#include <QString>#include <QMessageBox>#include <QMesh>#include <QUrl>#include <QSlider>#include <QVBoxLayout>#include <QHBoxLayout>#include <QLabel>#include <scene.h>namespace Ui {class ModelViewer;}class ModelViewer : public QMainWindow{Q_OBJECTpublic:explicit ModelViewer(QWidget *parent = nullptr);~ModelViewer();void SetLayout();protected:bool eventFilter(QObject *obj, QEvent *event);signals:void KeyPressed();private slots:void on_actionOpen_File_triggered();private:Ui::ModelViewer *ui;QSlider *createSlider();Scene *scene;QString currentFile = "";};#endif // MODELVIEWER_H

3.编写场景3D模型控制程序scene.cpp:

 #include "scene.h"#include "modelviewer.h"Scene::Scene(Qt3DExtras::Qt3DWindow *view, QObject *parent) : QObject (parent){rootEntity = new Qt3DCore::QEntity();view->setRootEntity(rootEntity);view->defaultFrameGraph()->setClearColor(QColor(QRgb(0x4d4d9f)));//0x42f4bcCamera(view);StartScene();}void Scene::Camera(Qt3DExtras::Qt3DWindow *view){Qt3DRender::QCamera *camera = view->camera();camera->lens()->setPerspectiveProjection(45.0f,16.0f/9.0f, 0.1f, 10000.0f);camera->setPosition(QVector3D(0, 0, 4000));camera->setViewCenter(QVector3D(0, 0, 0));}void Scene::StartScene(){model = new Qt3DCore::QEntity(rootEntity);Qt3DExtras::QTorusMesh *torusMesh = new Qt3DExtras::QTorusMesh(model);torusMesh->setRadius(5);torusMesh->setMinorRadius(1);torusMesh->setRings(100);torusMesh->setSlices(20);model->addComponent(torusMesh);SetupTransform();SetupMaterial();SetupLighting();}void Scene::NewScene(Qt3DRender::QMesh *mesh){delete model;model = new Qt3DCore::QEntity(rootEntity);SetupMesh(mesh);SetupTransform();SetupMaterial();SetupLighting();}void Scene::SetupMesh(Qt3DRender::QMesh *mesh){model->addComponent(mesh);}void Scene::SetupTransform(){transform = new Qt3DCore::QTransform(model);transform->setScale3D(QVector3D(1, 1, 1));transform->setRotation(QQuaternion::fromAxisAndAngle(QVector3D(1, 0, 0), 0));model->addComponent(transform);}void Scene::SetupMaterial(){Qt3DRender::QMaterial *material = new Qt3DExtras::QPhongMaterial(model);model->addComponent(material);}void Scene::SetupLighting(){Qt3DCore::QEntity *lightEntity = new Qt3DCore::QEntity(rootEntity);light = new Qt3DRender::QDirectionalLight(lightEntity);light->setColor("white");light->setIntensity(1);light->setWorldDirection(QVector3D(0,0,-1));lightEntity->addComponent(light);}void Scene::KeyControls(QKeyEvent *event){if (event->modifiers().testFlag(Qt::ControlModifier)){if(event->key()==Qt::Key_Up){transform->setRotationX(transform->rotationX()-10);}if(event->key()==Qt::Key_Down){transform->setRotationX(transform->rotationX()+10);}if(event->key()==Qt::Key_Left){transform->setRotationY(transform->rotationY()-10);}if(event->key()==Qt::Key_Right){transform->setRotationY(transform->rotationY()+10);}}else if (event->modifiers().testFlag(Qt::ShiftModifier)) {if(event->key()==Qt::Key_Up){transform->setTranslation(QVector3D(transform->translation().x(),transform->translation().y(),transform->translation().z()-30));}if(event->key()==Qt::Key_Down){transform->setTranslation(QVector3D(transform->translation().x(),transform->translation().y(),transform->translation().z()+30));}}else{if(event->key()==Qt::Key_Up){transform->setTranslation(QVector3D(transform->translation().x(),transform->translation().y()+30,transform->translation().z()));}if(event->key()==Qt::Key_Down){transform->setTranslation(QVector3D(transform->translation().x(),transform->translation().y()-30,transform->translation().z()));}if(event->key()==Qt::Key_Left){transform->setTranslation(QVector3D(transform->translation().x()-30,transform->translation().y(),transform->translation().z()));}if(event->key()==Qt::Key_Right){transform->setTranslation(QVector3D(transform->translation().x()+30,transform->translation().y(),transform->translation().z()));}}}void Scene::LightXChanged(int angle){light->setWorldDirection(QVector3D(angle,light->worldDirection().y(),light->worldDirection().z()));}void Scene::LightYChanged(int angle){light->setWorldDirection(QVector3D(light->worldDirection().x(),angle,light->worldDirection().z()));}void Scene::LightZChanged(int angle){light->setWorldDirection(QVector3D(light->worldDirection().x(),light->worldDirection().y(),angle));}

4.编写场景模型控制程序头文件scene.h

#ifndef SCENE_H#define SCENE_H#include <QObject>#include <QWidget>#include <Qt3DCore/QEntity>#include <Qt3DRender/QCamera>#include <Qt3DRender/QPointLight>#include <Qt3DRender/QDirectionalLight>#include <Qt3DCore/QTransform>#include <Qt3DWindow>#include <Qt3DExtras/QForwardRenderer>#include <Qt3DExtras/QPhongMaterial>#include <Qt3DExtras/QTorusMesh>#include <QKeyEvent>#include <QTransform>#include <QMesh>class Scene : public QObject{Q_OBJECTpublic:explicit Scene(Qt3DExtras::Qt3DWindow *, QObject *parent=nullptr);void NewScene(Qt3DRender::QMesh *);void KeyControls(QKeyEvent *event);public slots:void LightXChanged(int angle);void LightYChanged(int angle);void LightZChanged(int angle);private:Qt3DCore::QEntity *rootEntity;Qt3DCore::QEntity *model;Qt3DCore::QTransform *transform;Qt3DRender::QDirectionalLight *light;void StartScene();void Camera(Qt3DExtras::Qt3DWindow *view);void SetupMesh(Qt3DRender::QMesh *mesh);void SetupTransform();void SetupMaterial();void SetupLighting();};#endif // SCENE_H

编辑主函数main.c

 #include "modelviewer.h"#include <QApplication>int main(int argc, char *argv[]){QApplication a(argc, argv);ModelViewer *modelViewer =new ModelViewer();modelViewer->show();modelViewer->setWindowState(Qt::WindowMaximized);return a.exec();}

5.QT配置文件3DModelViewer.pro

 #-------------------------------------------------## Project created by QtCreator 2019-04-25T13:57:37##-------------------------------------------------QT       += core gui 3dcore 3drender 3dinput 3dextrasgreaterThan(QT_MAJOR_VERSION, 4): QT += widgetsTARGET = 3DModelViewerTEMPLATE = app# The following define makes your compiler emit warnings if you use# any feature of Qt which has been marked as deprecated (the exact warnings# depend on your compiler). Please consult the documentation of the# deprecated API in order to know how to port your code away from it.DEFINES += QT_DEPRECATED_WARNINGS# You can also make your code fail to compile if you use deprecated APIs.# In order to do so, uncomment the following line.# You can also select to disable deprecated APIs only up to a certain version of Qt.#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0CONFIG += c++11SOURCES += \main.cpp \modelviewer.cpp \scene.cppHEADERS += \modelviewer.h \scene.hFORMS += \modelviewer.ui# Default rules for deployment.qnx: target.path = /tmp/$${TARGET}/binelse: unix:!android: target.path = /opt/$${TARGET}/bin!isEmpty(target.path): INSTALLS += target

6.整体文件夹架构:

效果演示

“File->Open 打开一个3D模型文件. \n”
“利用方向键可平移模型. \n”
“利用shift + 方向键可缩放模型. \n”
“利用ctrl + 方向键可旋转模型. \n”
“利用右侧的滑块可调整灯光位置.”


注意:本文使用的模型是处理后的.obj格式,模型不予提供。

由于csdn限制,视频只能压缩成3倍速10帧300×200的gif格式

参考资料

https://github.com/reybar/3DModelViewer

嵌入式系统大作业——基于QT的3D模型展示相关推荐

  1. 智能嵌入式系统大作业(1)

    计算机科学与工程学院 | 智能嵌入式系统大作业(1) 题目:对于智能音箱--小米Sound的调研报告 班级:\姓名:\学号:\日期: 得分:\ 评语: 目录 题目:对于智能音箱--小米Sound的调研 ...

  2. 【C++课程设计】期末大作业 - 基于Qt开发的中国象棋软件

    1 题目 基于Qt的中国象棋软件开发 本博客只是简略的描述论文的大致结构.框架,以及软件开发的大致过程.有兴趣的参考原文档资料. 2总体设计与主要功能 2.1概述 中国象棋是起源于中国的一种棋,属于二 ...

  3. matlab求解多自由度振动系统,【2017年整理】1-《机械振动基础》大作业,基于matlab的多自由度振动.doc...

    [2017年整理]1-<机械振动基础>大作业,基于matlab的多自由度振动 <机械振动基础>大作业 (2016年春季学期) 题目多自由度振动系统的固有频率和固有阵型 姓 名学 ...

  4. 嵌入式期末大作业——家用智能晾衣杆

    嵌入式期末大作业--家用智能晾衣杆 目录 嵌入式期末大作业--家用智能晾衣杆 前言 一.项目介绍 1.项目背景 2.项目构思 二.系统设计 1.系统概述 2.设计思路 3.设计草图 三.硬件设计 1. ...

  5. 嵌入式课程设计linux,嵌入式系统课程设计--基于U盘的linux操作系统的构建

    嵌入式系统课程设计--基于U盘的linux操作系统的构建 1 课程设计报告课程设计报告 课程名称课程名称 嵌入式系统课程设计嵌入式系统课程设计 设计题目设计题目基于基于 U盘的盘的 linux 操作系 ...

  6. 数字信号处理大作业——基于matlab R2019a的男声变女声资料汇总与代码

    @数字信号处理大作业--基于matlab R2019a的男声变女声资料汇总与代码 概述 参考了很多前人的资料,发现很多函数已经过时了,而且从我通过VIP下载的代码来看,代码的逻辑不是很清晰,废话也多, ...

  7. 数字图像处理——大作业 基于车道信息的违法车辆车牌识别

    数字图像处理--大作业 基于车道信息的违法车辆车牌识别 一.车牌识别研究现状与分析 二.车牌识别算法原理 2.1 车牌定位 2.1.1 基于RGB阈值的车牌区域初定位 2.1.2 基于数学形态学的车牌 ...

  8. HTML期末大作业~基于HTML+CSS+JavaScript旅游网站设计与实现(6个页面)

    HTML期末大作业~HTML+CSS+JavaScript旅游网站设计与实现->绿色古典的旅游度假景区(6个页面) 临近期末, 你还在为HTML网页设计结课作业,老师的作业要求感到头大?HTML ...

  9. 操作系统大作业 基于Linux的模拟进程调度算法 运用c++语言编程 在VMware虚拟机里 centos 亲自写亲自测试 代码 说明书

    发布文章 博文管理我的博客退出 Trash Temp 操作系统大作业 基于Linux的模拟进程调度算法 运用c++语言编程 在VMware虚拟机里 centos 亲自写亲自测试 代码 说明书 @[TO ...

最新文章

  1. JavaScript初学者编程题(11)
  2. Java:基础面试题
  3. 皮一皮:高手。。。真是高手
  4. J - Max Sum
  5. java 字符串子串_java实现字符串匹配求两个字符串的最大公共子串
  6. 分享适合程序员使用17 张壁纸
  7. 洛谷P3349:小星星(容斥dp)
  8. 向数组添加元素 java_java如何向数组里添加元素
  9. matplotlib图表介绍
  10. The LLVM Compiler Infrastructure | LLVM编译器基础设施
  11. 全军出击机器人进房间_科沃斯扫地机器人T8 POWER/MAX开箱测评推荐
  12. HTML常用的元素介绍
  13. Python每天练习——小程序006
  14. Matlab中图形对象属性gca使用
  15. 何为ISM频段?ISM频段主要频率有哪些?
  16. matlab xaxislocation,x轴和y轴位置
  17. 带你认识40G单纤双向光模块-QSFP+ BiDi光模块
  18. HyperLedger Fabric - 超级账本(8)Node测试
  19. ShowMeAI —— Show u 三连
  20. MCE | HIV 衣壳蛋白有望成为 HIV 治疗新靶标

热门文章

  1. 华为 SWE 实习岗 笔试题 JAVA
  2. 软件测试 中静态测试与动态测试的区别
  3. 云计算方向研究热点、 云计算有怎样的发展前景?
  4. 怎么进行用户体验与可用性测试?
  5. 北斗GPS同步时钟(授时系统)技术原理详解
  6. matlab如何画动态圆弧,几何画板动态演示转弧成球的过程
  7. 干货!区块链入门、进阶、行业专家观点!1000篇好文帮你破解区块链密码!(中篇)...
  8. Html主要内容总结
  9. 进程、线程知识点总结和同步(消费者生产者,读者写者三类问题)、互斥、异步、并发、并行、死锁、活锁的总结
  10. MATLAB 数据频数统计