Search code examples
c++qtqt3d

How to zoom toward a 3D mesh with qt?


I'm using a Wheelevent to Zoom in/out in a QWidget view,in use the event to translate the QCamera, is there a solution from the qt api to move toward a point or zoom with the camera to a specific point? I searched in many sections but did'nt find something useful unfortunately.


Solution

  • Edit: Stefan Reinhardt suggested to use QAbstractCameraController to achieve what you want to do. The example I provided is a quick-and-dirty solution. I agree that using the camera controller is the way intended in Qt3D.


    The Qt3D API doesn't support this directly, but you can implement it easily yourself.

    Here is a minimally working example, that should get you started (note, that you have to adjust the upvector, when scrolling past the view center I guess):

    main.cpp:

    #include <QApplication>
    #include "graphicswindow.h"
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        GraphicsWindow graphicsWindow;
        graphicsWindow.show();
        return a.exec();
    }
    

    graphicswindow.h:

    #include <Qt3DExtras/Qt3DWindow>
    #include <Qt3DCore/QEntity>
    
    class GraphicsWindow : public Qt3DExtras::Qt3DWindow {
    public:
        GraphicsWindow();
        void wheelEvent ( QWheelEvent * event ) override;
    
    private:
        Qt3DCore::QEntity *createScene();
    };
    

    graphicswindow.cpp:

    #include "graphicswindow.h"
    #include <QMouseEvent>
    #include <QVector3D>
    #include <Qt3DRender/QCamera>
    #include <Qt3DRender/QMaterial>
    #include <Qt3DExtras/QGoochMaterial>
    #include <Qt3DExtras/QCuboidMesh>
    
    GraphicsWindow::GraphicsWindow() : Qt3DExtras::Qt3DWindow() {
        // You could also create a dedicated setup method
        Qt3DCore::QEntity *root = createScene();
        setRootEntity(root);
        Qt3DRender::QCamera *camera = this->camera();
        camera->lens()->setPerspectiveProjection(45.0f, 16.0f/9.0f, 0.1f, 1000.0f);
        camera->setPosition(QVector3D(20.0, 20.0, 20.0f));
        camera->setViewCenter(QVector3D(0, 0, 0));
    }
    
    void GraphicsWindow::wheelEvent(QWheelEvent *event) {
        QVector3D camPos = this->camera()->position();
        camPos.normalize();
        camPos = this->camera()->position() - QVector3D(event->delta() / 300.f,
                                                    event->delta() / 300.f,
                                                    event->delta() / 300.f);
        this->camera()->setPosition(camPos);
    }
    
    
    Qt3DCore::QEntity* GraphicsWindow::createScene() {
        Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity;
    
        Qt3DRender::QMaterial *material = new Qt3DExtras::QGoochMaterial(rootEntity);
    
        //Cube
        Qt3DCore::QEntity *cubeEntity = new Qt3DCore::QEntity(rootEntity);
        Qt3DExtras::QCuboidMesh *cubeMesh = new Qt3DExtras::QCuboidMesh;
    
        cubeEntity->addComponent(cubeMesh);
        cubeEntity->addComponent(material);
    
        return rootEntity;
    }