![](/img/trans.png)
[英]How to create QQuickWindow as a child from a C++ extended QQuickItem?
[英]How to set the QQuickItem position at a precise frame from C++?
我的移動應用程序使用QML
范式下的OpenGL
。
我的GL場景的相機方向已同步到移動設備的運動傳感器(磁力計和加速度計)。 我還在該3D場景的頂部顯示2D標簽,該標簽在屏幕上的位置需要與我的GL場景中的給定3D位置相對應。 這些標簽是常規QML項,我可以從我的應用程序的C ++端進行控制。
為此,我直接連接到QQuickWindow::beforeSynchronising()
信號,其中相機方向與運動傳感器同步。 然后,我在屏幕上投影3D點以找到標簽的位置,最后調用QQuickItem::setPosition()
。
通過直接連接到QQuickWindow::beforeRendering()
信號,可以照常渲染GL場景。
MyAppController::MyAppController() : QObject() {
connect(window, SIGNAL(beforeSynchronising()), this, SLOT(sync()), Qt::DirectConnection);
connect(window, SIGNAL(beforeRendering()), this, SLOT(render()), Qt::DirectConnection);
m_camera = ...; // create camera
m_scene = ...; // create GL scene
m_quickItem = ...; // load label QML item
// start updating the window at a constant frame rate
QTimer* timer = new QTimer(this);
connect (timer, SIGNAL(timeout()), this, SLOT(update()));
timer->start(1000.0 / 60.0); // 60 FPS
}
MyAppController::sync() {
m_camera->syncWithMotionSensor();
// use camera matrix to calculate the projection of a 3D point on the screen
QPointF pos = ...;
m_quickItem->setPosition(pos); // set the label position
}
MyAppController::render() {
m_scene->draw(); // OpenGL code
}
一切都很好,只不過我的標簽似乎比我的GL場景晚了一幀,而且我想我理解為什么:從QSGRendering線程調用QQuickItem::setPosition()
顯然為時已晚,無法為QSGNode
更新幀。 已為該項目安排了更新,但是直到下一幀才生效。 因此1幀延遲。
您可能會認為它還不錯,但是它確實會產生奇怪的效果,並且不利於閱讀標簽上的內容,因為眼睛也跟隨背景(請記住相機已與設備運動傳感器同步)。
我嘗試使用QQuickWindow::afterAnimating()
信號,但延遲更大。 這是正常現象,因為此信號是從GUI線程發出的,因此我們對QSGRenderThread將在哪個幀上進行同步的控制甚至更少。
所以我的問題是,如何才能在精確的框架中從C ++實現QML項目的定位? 使用QML甚至可能嗎? 如果我的標簽是純C ++ QQuickItems更好,並且不是使用我自己的函數來確保QSGNode能夠接收更新,而不是調用setPosition()呢?
因此,答案是在渲染GL場景后簡單地同步攝像機和標簽的位置。 這樣,我們可以確定在下一幀將考慮標簽的位置。 最終解決方案如下所示:
MyAppController::sync() {
m_scene->prepare(); // uses the camera matrix from previous frame
m_camera->syncWithMotionSensor(); // update camera matrix
// use camera matrix to calculate the projection of a 3D point on the screen
QPointF pos = ...;
m_quickItem->setPosition(pos); // set the label position, will be updated on the next frame
}
MyAppController::render() {
m_scene->draw(); // execute OpenGL code
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.