Details
-
Bug
-
Resolution: Unresolved
-
P2: Important
-
None
-
5.13.0
-
None
Description
The following code shows a 3D Scene with two spheres with centers at (20,-10,0) and (20,10,0) and radii 0.5.
Both spheres are below an empty QEntity called rootEntity.
Calling viewEntity on this rootEntity, should result in a spherical bounding volume centered at (20,0,0) with radius (20+2*0.5)/2.
Instead the program returns:
Bounding Sphere: QVector3D(12.1432, 2.14455, -1.32699e-08) 14.9644
Calling viewEntity on sphere1 and sphere2 gave the desired results of:
Bounding Sphere: QVector3D(20, 10, -2.18557e-08) 0.5
Bounding Sphere: QVector3D(20, -10, -2.18557e-08) 0.5
My best guess is that there is an error inside the ComputeFilteredBoundingVolumeJob.cpp on lines 61-68, but I was not able to nail it down.
#include <QApplication> #include <QWidget> #include <QLoggingCategory> #include <QVBoxLayout> #include <QFrame> #include <Qt3DRender/QRenderSettings> #include <Qt3DCore/QTransform> #include <Qt3DRender/QCamera> #include <Qt3DExtras/QSphereMesh> #include <Qt3DExtras/QDiffuseSpecularMaterial> #include <Qt3DExtras/QForwardRenderer> #include <Qt3DExtras/Qt3DWindow> #include <Qt3DRender/QCamera> #include <Qt3DRender/QCameraLens> #include <QPushButton> Qt3DCore::QEntity* createSphereMesh() { auto sphereMat = new Qt3DExtras::QDiffuseSpecularMaterial; sphereMat->setDiffuse(QColor(Qt::blue)); auto mesh = new Qt3DExtras::QSphereMesh(); mesh->setRadius(0.5); auto meshEntity = new Qt3DCore::QEntity; meshEntity->addComponent(mesh); meshEntity->addComponent(sphereMat); return meshEntity; } int main(int argc, char* argv[]) { QApplication a(argc, argv); auto view = new Qt3DExtras::Qt3DWindow(); view->defaultFrameGraph()->setClearColor(QColor(127, 127, 127)); auto settings = view->renderSettings(); settings->setActiveFrameGraph(view->activeFrameGraph()); auto rootEntity = new Qt3DCore::QEntity(); view->setRootEntity(rootEntity); auto sphere1 = createSphereMesh(); sphere1->setParent(rootEntity); auto trafo1 = new Qt3DCore::QTransform; trafo1->setTranslation(QVector3D(20, 10, 0)); sphere1->addComponent(trafo1); auto sphere2 = createSphereMesh(); sphere2->setParent(rootEntity); auto trafo2 = new Qt3DCore::QTransform; trafo2->setTranslation(QVector3D(20, -10, 0)); sphere2->addComponent(trafo2); QObject::connect(view->camera()->lens(), &Qt3DRender::QCameraLens::viewSphere, [&](const QVector3D& center, float radius) { qDebug() << "Bounding Sphere:" << center << radius; auto boundingSphereEntity = new Qt3DCore::QEntity; auto sphereMat = new Qt3DExtras::QDiffuseSpecularMaterial; sphereMat->setAlphaBlendingEnabled(true); sphereMat->setDiffuse(QColor(255,255,255,80)); auto mesh = new Qt3DExtras::QSphereMesh(); mesh->setRadius(radius); boundingSphereEntity->addComponent(sphereMat); boundingSphereEntity->addComponent(mesh); auto trafoAll = new Qt3DCore::QTransform; trafoAll->setTranslation(center); boundingSphereEntity->addComponent(trafoAll); boundingSphereEntity->addComponent(mesh); boundingSphereEntity->addComponent(sphereMat); boundingSphereEntity->setParent(rootEntity); }); auto container = QWidget::createWindowContainer(view); auto viewAllBtn = new QPushButton("View Root Entity"); QObject::connect(viewAllBtn, &QPushButton::clicked, [&]() { view->camera()->viewEntity(rootEntity); }); QFrame frame; frame.setFixedSize(500, 500); frame.setLayout(new QVBoxLayout); frame.layout()->addWidget(container); frame.layout()->addWidget(viewAllBtn); frame.show(); return a.exec(); }
I further investigated, as I really needed this feature and stumbled across the source tst_boundingsphere.cpp in qt3d/tests/auto/render/boundingsphere.
There I found the following interesting line:
QTest::newRow("CubeMesh") << "qrc:/cube.qml" << QVector3D(0.0928356f, -0.212021f, -0.0467958f) << 1.07583f; // weird! |
It is indeed not obvious, why a cube mesh of extents 1. should have a bounding volume like this. At least the radius of the bounding sphere should be sqrt(3)/2. The center of the cube should be something like (0.5,0.5,0.5).
I guess the problem lies in the implementation of the qt3d/src/render/frontend/sphere.cpp, as there is a fault in the implementation of an invalid sphere. Assume that there is an void entity without any points, then it will have a bounding sphere with center=(0,0,0) with r=0. Assume now, that you will another bounding sphere with center=(1,1,1) and r=0.1.
Then expandToContain should just give center=(1,1,1) and r=0.1, but expandToContain will give something around center=(0.55,0.55,0.55) and r=0.55.
I would suggest to implement invalid spheres being the ones having a radius being < 0.
In case the method transformed is called on an invalid sphere, there should be nothing to do.
Attachments
Gerrit Reviews
For Gerrit Dashboard: QTBUG-78313 | ||||||
---|---|---|---|---|---|---|
# | Subject | Branch | Project | Status | CR | V |
275167,6 | Fix for bounding volume handling and calculation | 5.13 | qt/qt3d | Status: ABANDONED | 0 | 0 |
275666,5 | Fix for bounding volume handling and calculation | 5.13 | qt/qt3d | Status: MERGED | +2 | 0 |