如何混合QT3D和Qopengl

发布于 2025-02-13 13:48:46 字数 4356 浏览 0 评论 0原文

早上好,

我开发了一个应用程序,该应用程序呈现纹理的立方体,并使用四局旋转它。 我使用QT6和Qopengl函数来完成这项工作。

然后,我想加载完整的3D模型(不使用着色器或OpenGL功能绘制它)。因此,我一直在寻找许多方法,最终使用QT3D的示例来加载文件。

问题是我需要对象的模型矩阵,以便可以在其上执行转换。

我知道我可以使用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管道中,并使用ModelView绘制和操纵其他对象。

当然,我上面编写的代码不是正确的,因为BodyTransform是Qtransform,摄影机是QCAMERA。它们不是矩阵(qmatrix4x4类)。

编辑: 我做的是我存储了类似的投影和模型矩阵值:

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

然后,我计算了ModelView矩阵(ViewMatrix和Model的产品)

,然后:

   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管道中,并试图绘制坐标系统,但没有'工作。

谢谢大家的帮助。

Good morning,

I developed an application that renders a textured cube and rotates it using quaternions.
I used Qt6 and QOpenGL functions to make this work.

Then I wanted to load a full 3D model ( without drawing it using shaders or opengl functions ). So I kept looking for many methods and ended up using an example with QT3D to load a file.PLY.

The problem is that I need the model matrix of the object so that I can perform transformations on it.

I know I can do it using QTransform class functions but I don't want to do that.
Here is the code I used to load the ply file. It works perfectly

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();
}

Now I think the bodyTransform in this example is equivalent to the model matrix since we can apply transformations on it.
And the camera entity is equivalent to gluLookAt or lookAt( QopenGL function).

But in the old code where I can rotate the model, I'm working with QOpenGL functions and I don't want to change all of it.

My question is the following:
Is it possible to keep working with QOpenGL and inside the paintGL function, use the QT3D library to just load the model and then assign a model view matrix to it that can be manipulated using QOpenGL functions and not QTransform.

In the example of QT3D, I tried to draw objects using the old OpenGL functions like glvertex but they weren't rendered in the scene.

I want to do something like this:

 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();

I mean I want to load both projection and modelview matrices into the openGL pipeline and use the modelview to draw and manipulate other objects.

Of course the code I wrote above isn't correct because bodyTransform is a QTransform and cameraEntity is a QCamera. they're not Matrices (QMatrix4x4 class).

EDIT:
What I did is that I store the projection and model matrices values like this:

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

then I calculated the modelview matrix ( product of viewmatrix and model)

And then:

   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

I loaded them in the OpenGL pipeline and tried to draw a coordinate system but that didn't work.

Thank you all for your help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

ら栖息 2025-02-20 13:48:46

回答您的问题有点困难,因为它充满了东西,但我还是会尝试回答:

也许关于您的问题“可以将QT3D和OpenGL结合起来吗?”?好吧,这绝对是可能的,但是您必须获取已在QT3D中加载的所有数据并将其传输到OpenGL,这将是很多工作。

因此,有几个建议/备注:

  1. 坚持其中一个。我确实在
  2. 使用OpenGL中的着色器(与您的具体问题无关)。它们并不困难,比旧的可编程管道更灵活。相信我,我发现它们真的很可怕,但是如果您可以编程C ++(显然您可以),那么您就有能力编程着着色器。找到一个简单的教程并在OpenGL中实现一个简单的着色器,所有黑魔法都将变得更加合理。
  3. 使用qsceneloader在QT3D中加载模型。这将自动加载所有相应的材料等。QT3D在后台使用Assimp。当然,您也可以使用Assimp来为您的现有代码加载模型。但这是很多工作,我坚持QT3D。
  4. 您为什么不想使用qtransform?对我来说,似乎最大的一步是加载模型并展示它。添加简单的功能以使用转换矩阵旋转对象不应该很难。就像您甚至已经提到的一样,您可以从转换中获取矩阵并将其设置。表示您可以将其作为4x4矩阵操作,并将结果设置为转换。
  5. 也许有点太复杂了,但是如果您有兴趣了解如何在QT3D中操纵对象,我还实现了a qt3dgizmo 。它需要一些工作来设置,因为您需要一个专门的分支机构,以确保它始终是其他对象的上方绘制的,但否则可以正常工作。

这是一个很好的第一个问题,您提出了很多示例和代码,也许只是尝试使它更简洁,下次很难回答这样的问题;)制作)

It's a bit difficult to answer your question because it's so packed with things but I'll try to answer anyways:

Maybe regarding your question "is it possible to combine Qt3D and OpenGL"? Well, it's definitely possible but you'd have to get all the data that has been loaded in Qt3D and transfer it to OpenGL, that's going to be a lot of work.

So a couple of suggestions/remarks:

  1. Stick to one of either. I did mix Qt3D and OpenGL in my Qt3DWidget implementation but to render Qt3D offscreen and then draw that using OpenGL, that's something different.
  2. Use shaders in OpenGL (unrelated to your concrete problem). They're not that difficult and give you way more flexibility than the old programmable pipeline. Believe me, I found them really scary but if you can program C++ (which you obviously can) then you are more than capable of programming shaders. Find a simple tutorial and implement a simple shader in OpenGL and all the black magic will become more reasonable.
  3. Use QSceneLoader to load models in Qt3D. This will automatically load all respective materials, etc. Qt3D uses Assimp in the background. You could of course also use Assimp for your existing code to load the model. But it's a lot of work, I'd stick to Qt3D.
  4. Why exactly don't you want to use QTransform? For me it seems the biggest step was to load the model and show it. Adding simple functionality to rotate the object using the transform's matrix shouldn't be hard. Like you even already mentioned, you can get the matrix from the transform and also set it. Means you can manipulate it as a 4x4 matrix and set the result on the transform.
  5. Maybe a bit too complex but if you're interested in understanding more how to manipulate objects in Qt3D, I also implemented a Qt3DGizmo. It takes a bit of work to setup because you need a dedicated branch for the gizmo to make sure it's always drawn ontop of other objects but works fine otherwise.

It's a good first question you asked with a lot of examples and code, maybe just try to make it a bit more concise next time it's a bit difficult to answer like this ;) (which I guess is apparent in the many points I wanted to make)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文