如何混合使用QT3D和QopenGL

pcww981p  于 2022-11-04  发布在  其他
关注(0)|答案(1)|浏览(307)

你好,
我开发了一个应用程序,它可以渲染一个带纹理的立方体,并使用四元数旋转它。我使用了Qt6和QOpenGL函数来实现这一功能。
然后我想加载一个完整的3D模型(不用着色器或opengl函数绘制)。所以我一直在寻找许多方法,最后用QT3D的一个例子来加载file.PLY。
问题是,我需要对象的模型矩阵,这样我才能对它执行转换。
我知道我可以用QTransform类函数来实现,但我不想这么做。下面是我用来加载ply文件的代码。它运行得很好

int main(int argc, char* argv[])

{

QApplication app(argc, argv);
Qt3DExtras::Qt3DWindow *view = new Qt3DExtras::Qt3DWindow();
view->defaultFrameGraph()->setClearColor(QColor(QRgb(0x4d4d4f)));
view->defaultFrameGraph()->setClearColor(QColor(255,255,255,1));
QWidget *container = QWidget::createWindowContainer(view);
QSize screenSize = view->screen()->size();
container->setMinimumSize(QSize(200, 100));
container->setMaximumSize(screenSize);
QWidget *widget = new QWidget;
QHBoxLayout *hLayout = new QHBoxLayout(widget);
hLayout->addWidget(container, 1);

widget->setWindowTitle(QStringLiteral("Satellite"));

Qt3DInput::QInputAspect *input = new Qt3DInput::QInputAspect;
view->registerAspect(input);

// Root entity
Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity();

// Camera
Qt3DRender::QCamera *cameraEntity = view->camera();

cameraEntity->lens()->setPerspectiveProjection(45.0f, 16.0f/9.0f, 0.1f, 100000.0f);//projection

 cameraEntity->setPosition(QVector3D(-40000, 40000, 40000.0f));
 cameraEntity->setUpVector(QVector3D(0, 0, 1));
//cameraEntity->setViewCenter(QVector3D(0, 0, 10000));
cameraEntity->setViewCenter(QVector3D(0, 0, 10));

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(cameraEntity->position());
lightEntity->addComponent(lightTransform);

//Loading .ply data
const QUrl data = QUrl::fromLocalFile("PATH/challengeone.PLY");
qDebug() << data << data.isValid() << data.toLocalFile() << QFileInfo(data.toLocalFile()).exists() << data.fileName();
qDebug() << QDir::currentPath();
Qt3DRender::QMesh *bodyMesh = new Qt3DRender::QMesh();
bodyMesh->setMeshName("bodyMesh");
bodyMesh->setSource(data);

Qt3DCore::QTransform *bodyTransform = new Qt3DCore::QTransform;
bodyTransform->setScale3D(QVector3D(90.0, 90.0, 90.0));

bodyTransform->setRotationX(90.0);
Qt3DExtras::QPhongMaterial *bodyMaterial = new Qt3DExtras::QPhongMaterial();
Qt3DCore::QEntity *plyEntity = new Qt3DCore::QEntity(rootEntity);
plyEntity->addComponent(bodyMesh);
plyEntity->addComponent(bodyMaterial);
plyEntity->addComponent(bodyTransform);

// Set root object of the scene
view->setRootEntity(rootEntity);

// Show window
widget->show();
widget->resize(1200, 800);

return app.exec();
}

现在我认为这个例子中的bodyTransform等价于模型矩阵,因为我们可以在它上面应用变换。而相机实体等价于gluLookAt或lookAt(QopenGL函数)。
但在我可以旋转模型的旧代码中,我使用的是QOpenGL函数,我不想全部更改。
我的问题如下:是否可以继续使用QOpenGL并在paintGL函数中使用QT3D库加载模型,然后为其分配一个模型视图矩阵,该矩阵可以使用QOpenGL函数而不是QTransform进行操作。
在QT3D的示例中,我尝试使用旧的OpenGL函数(如glvertex)绘制对象,但它们没有在场景中渲染。
我想做这样的事情:

glMatrixMode(GL_PROJECTION);
glLoadMatrixf(cameraEntity->lens());

glMatrixMode(GL_MODELVIEW);
glLoadMatrixf(bodyTransform);
gluLookAt(2.0,2.0,0.0,0.0,0.0,-5.0,0.0,1.0,0.0);

glTranslatef(0.0,0.0,-5.0);

glRotatef(180.0,0.0,1.0,0.0);
glRotatef(-90.0,1.0,0.0,0.0);

glScalef(0.4,0.4,0.4);
DrawOribtalFrame();

我的意思是我想把投影和模型视图矩阵都加载到openGL管道中,并使用模型视图来绘制和操作其他对象。
当然我上面写的代码是不正确的,因为bodyTransform是一个QTransform,cameraEntity是一个QCamera。它们不是矩阵(QMatrix4x4类)。
编辑:我所做的是存储投影和模型矩阵值,如下所示:

projection=cameraEntity->projectionMatrix();
viewmatrix=cameraEntity->viewMatrix();
model=bodyTransform->matrix();

然后计算模型视图矩阵(视图矩阵和模型的乘积)
然后道:

glMatrixMode(GL_PROJECTION);

   glLoadMatrixf(projection.constData());
   glMatrixMode(GL_MODELVIEW);

   glLoadMatrixf(modelview.constData());

   glTranslatef(0.0,0.0,-5.0);
   glRotatef(180.0,0.0,1.0,0.0);

   glRotatef(-90.0,1.0,0.0,0.0);
   glScalef(0.4,0.4,0.4);

//draw coordinate system

我把它们加载到OpenGL管道中,试图绘制一个坐标系,但没有成功。
谢谢大家的帮助。

oipij1gg

oipij1gg1#

回答你的问题有点困难,因为问题太多了,但我还是会尽量回答的:
也许关于你的问题“有没有可能合并Qt 3D和OpenGL”?嗯,这肯定是可能的,但你必须得到所有的数据,已加载到Qt 3D和传输到OpenGL,这将是一个很大的工作。
因此,有几点建议/意见:
1.我确实在Qt3DWidget实现中混合了Qt 3D和OpenGL,但是在屏幕外渲染Qt 3D,然后使用OpenGL绘制,这是不同的。
1.在OpenGL中使用着色器(与你的具体问题无关)。它们并不困难,而且比旧的可编程流水线给予你更多的灵活性。相信我,我发现它们真的很可怕,但是如果你能编写C++(你显然能),那么你就更有能力编写着色器。找一个简单的教程,在OpenGL中实现一个简单的着色器,所有的黑魔法都会变得更合理。
1.使用QSceneLoader在Qt 3D中加载模型。这将自动加载所有相应的材料等。Qt 3D在后台使用Assimp。当然,您也可以使用Assimp为您现有的代码加载模型。但这是一个很大的工作,我会坚持使用Qt 3D。
1.为什么你不想使用QTransform呢?对我来说,最大的一步似乎是加载模型并显示它。添加简单的功能来使用变换的矩阵旋转对象应该不难。就像你已经提到的,你可以从变换中获得矩阵并设置它。这意味着你可以将它作为一个4x 4矩阵来操作,并设置变换的结果。
1.也许有点太复杂了,但是如果你想了解更多如何在Qt 3D中操作对象的话,我还实现了一个Qt3DGizmo。它需要一些工作来设置,因为你需要一个专门的gizmo分支来确保它总是绘制在其他对象的上面,否则就可以正常工作。
这是一个很好的第一个问题,你问了很多例子和代码,也许只是尝试使它更简洁一点,下次它有点难以回答这样;)(我想这在我想说的许多观点中是显而易见的)

相关问题