前言
在 利用Qt结合openGL实现简易3D查看器 - 掘金 (juejin.cn)的基础上,增加Qt3D的支持。但Qt3D目前还不支持导入glb格式,需要改进。本文内容包括:1、Qt AssimpSceneImportPlugin插件改进;2、Qt3D引入。
一、AssimpSceneImportPlugin插件改进
一般采用下面方式加载AssimpSceneImportPlugin插件,可以发现是不支持glb格式的。
Qt3DRender::QSceneImporter* sceneImporter = Qt3DRender::QSceneImportFactory::create("assimp", QStringList());
bool bSupportGlb = sceneImporter->areFileTypesSupported(QStringList("glb"));
主要问题有两个地方:
- 第一个见:[QT3DS-4244] Qt3DRender::AssimpImporter与原生assimp库读取GLB_Header结构方式不一样导致无法加载glb/gltf模型 - Qt Bug Tracker
- 第二个是glb的纹理数据是直接嵌入到glb文件中的,需要适配一下,如下:
- 需要注意的是,stbi_load_from_memory分配的内存需要要通过stbi_image_free释放,且内存分配一般比较大。另外通过
QImage(const uchar *data, int width, int height, Format format...的方式构造QImage,是浅拷贝,不能马上通过释放内存,需要在合适的地方调用stbi_image_free。
2 Qt3D引入
只引入Qt3D的基本功能,比较简单,参考网上的例子即可。但里面还有很多问题,主要有:
- 和opengl绘制相比,性能非常差,大点的模型加载及渲染非常卡顿。
- 切换模型,析构Qt3DExtras::Qt3DWindow()会崩溃,具体原因不清楚
- 对模型的精细控制不太容易。
QVBoxLayout *vLayout = new QVBoxLayout(this);
vLayout->setContentsMargins(0, 0, 0, 0);
m_view = new Q3DWindowEx(this);
m_view->defaultFrameGraph()->setClearColor(color);
m_3dContainer = QWidget::createWindowContainer(m_view);
vLayout->addWidget(m_3dContainer);
Qt3DRender::QSceneImporter* sceneImporter = Qt3DRender::QSceneImportFactory::create("assimpEx", QStringList()); //todo memory leak?
sceneImporter->setSource(QUrl::fromLocalFile(m_modelPath));
Qt3DCore::QEntity *rootEntity = sceneImporter->scene();
m_view->setRootEntity(rootEntity);
m_cameraEntity = m_view->camera();
m_cameraEntity->lens()->setPerspectiveProjection(45.0f, 16.0f / 9.0f, 0.1f, 1000.0f);
m_cameraEntity->setPosition(m_view->getSuitableCameraPos());
m_cameraEntity->setUpVector(QVector3D(0, 0, 0));
m_cameraEntity->setViewCenter(QVector3D(0, 0, 0));
Qt3DCore::QEntity* lightEntity = new Qt3DCore::QEntity(rootEntity);
Qt3DRender::QPointLight* light = new Qt3DRender::QPointLight(lightEntity);
light->setColor("white");
light->setIntensity(1);
lightEntity->addComponent(light);
Qt3DCore::QTransform* lightTransform = new Qt3DCore::QTransform(lightEntity);
lightTransform->setTranslation(m_view->getSuitableLightPos());
lightEntity->addComponent(lightTransform);
Qt3DExtras::QFirstPersonCameraController* camController = new Qt3DExtras::QFirstPersonCameraController(rootEntity);
camController->setCamera(m_cameraEntity);
以上问题,以后再考虑修复。后面先将添加Vulkan绘制及cef预览模型,以补充功能。
源码:github.com/1995zyl/3D-…
上期: 利用Qt结合openGL实现简易3D查看器 - 掘金 (juejin.cn)