My QOpenGLWidget only produce a black screen

232 Views Asked by At

I'm trying to make a QOpenGlWidget of the qt part of this library (https://github.com/melowntech/vts-browser-cpp) and i'm currently with a black screen widget while all functions seems to be running fine. my widget cpp

#include "vtswidget.h"
#include <QGuiApplication>
#include <QMouseEvent>
#include <QWheelEvent>
#include <vts-browser/log.hpp>
#include <vts-browser/map.hpp>
#include <vts-browser/mapOptions.hpp>
#include <vts-browser/camera.hpp>
#include <vts-browser/navigation.hpp>
#include <vts-renderer/renderer.hpp>
#include <stdexcept>
#include <QSurface>
#include <QDebug>
#include <QTimer>
static Gl *openglFunctionPointerInstance;

void *openglFunctionPointerProc(const char *name)
{
    return (void*)openglFunctionPointerInstance->getProcAddress(name);
}

Gl::Gl(QSurface *surface) : surface(surface)
{}

void Gl::current(bool bind)
{
    if (bind)
        makeCurrent(surface);
    else
        doneCurrent();
}

void Gl::initialize()
{
    setFormat(surface->format());
    create();
    if (!isValid())
        throw std::runtime_error("unable to create opengl context");
}

void DataThread::run()
{
    vts::setLogThreadName("data");
    gl->current();
    vts::renderer::installGlDebugCallback();
    map->dataAllRun();
}


VtsWidget::VtsWidget(QWidget *parent) : QOpenGLWidget(parent)
{
    QTimer *timer = new QTimer(this);
    connect(timer, &QTimer::timeout, this, QOverload<>::of(&VtsWidget::update));
    timer->start(1000);
    QSurfaceFormat format;
        format.setVersion(3, 3);
        format.setProfile(QSurfaceFormat::CoreProfile);
    #ifndef NDEBUG
        format.setOption(QSurfaceFormat::DebugContext);
    #endif
        format.setDepthBufferSize(0);
        format.setStencilBufferSize(0);
        setFormat(format);

}

void VtsWidget::initializeGL() {

    setWindowTitle(tr("VTS Widget"));
    resize(QSize(800, 600));

       if (!this->context()) {
           qWarning("Failed to get current OpenGL context");
           return;
       }

       // Initialize the OpenGL functions for the current context
       if (!this->context()->isValid() || !this->context()->functions()) {
           qWarning("Failed to initialize OpenGL functions for the current context");
           return;
       }

       this->context()->functions()->initializeOpenGLFunctions();

        if (this->context() != nullptr) {
            if (this->context()->isValid()) {
                if (!this->context()->surface()) {
                    qWarning("Failed to get OpenGL surface for the current context");
                    return;
                }
            } else {
                qDebug() << "Invalid QSurfaceFormat";
                return;// Handle the case where the QSurfaceFormat is invalid.
            }
        } else {
            qDebug() << "surfacecontext is null";
            return;
            // Handle the case where surfacecontext is null.
        }

        dataThread.gl = std::make_shared<Gl>(this->context()->surface());
        dataThread.gl->initialize();
        dataThread.gl->current(false);

        gl = std::make_shared<Gl>(this->context()->surface());
        gl->setShareContext(dataThread.gl.get());
        gl->initialize();
        gl->current();
        gl->makeCurrent(this->context()->surface());
        openglFunctionPointerInstance = gl.get();
        vts::renderer::loadGlFunctions(&openglFunctionPointerProc);

        vts::MapCreateOptions mapopts;
        mapopts.clientId = "vts-browser-qt";
        map = dataThread.map = std::make_shared<vts::Map>(mapopts);
        map->setMapconfigPath(
                "http://192.168.4.104:9000/store/vts/gebco_global/mapConfig.json",
                "");
        camera = map->createCamera();
        navigation = camera->createNavigation();

        vtscontext = std::make_shared<vts::renderer::RenderContext>();
        vtscontext->bindLoadFunctions(map.get());
        view = vtscontext->createView(camera.get());

        dataThread.gl->moveToThread(&dataThread);
        dataThread.start();

        lastTime = std::chrono::high_resolution_clock::now();
}

VtsWidget::~VtsWidget()
{
    view.reset();
    navigation.reset();
    camera.reset();
    if (map)
        map->renderFinalize();
    dataThread.wait();
}


void VtsWidget::mouseMove(QMouseEvent *event)
{
    QPoint diff = event->globalPos() - lastMousePosition;
    lastMousePosition = event->globalPos();
    double n[3] = { (double)diff.x(), (double)diff.y(), 0 };
    if (event->buttons() & Qt::LeftButton)
        navigation->pan(n);
    if ((event->buttons() & Qt::RightButton)
        || (event->buttons() & Qt::MiddleButton))
        navigation->rotate(n);
}

void VtsWidget::mousePress(QMouseEvent *)
{}

void VtsWidget::mouseRelease(QMouseEvent *)
{}

void VtsWidget::mouseWheel(QWheelEvent *event)
{
    navigation->zoom(event->angleDelta().y() / 120.0);
}

bool VtsWidget::event(QEvent *event)
{
    switch (event->type())
    {
    case QEvent::MouseMove:
        mouseMove(dynamic_cast<QMouseEvent*>(event));
        return true;
    case QEvent::MouseButtonPress:
        mousePress(dynamic_cast<QMouseEvent*>(event));
        return true;
    case QEvent::MouseButtonRelease:
        mouseRelease(dynamic_cast<QMouseEvent*>(event));
        return true;
    case QEvent::Wheel:
        mouseWheel(dynamic_cast<QWheelEvent*>(event));
        return true;
    default:
            return QWidget::event(event);
    }
}

void VtsWidget::paintGL()
{

    auto currentTime = std::chrono::high_resolution_clock::now();
    double elapsedTime = std::chrono::duration_cast<std::chrono::microseconds>(
                currentTime - lastTime).count() * 1e-6;
    lastTime = currentTime;


    if (!isVisible())
        return;

    if (!gl->isValid())
        throw std::runtime_error("invalid gl context");

    gl->makeCurrent(this->context()->surface());
    QSize size = QWidget::size();

    // release build -> catch exceptions and close the window
    // debug build -> let the debugger handle the exceptions
#ifdef NDEBUG
    try
    {
#endif

        map->renderUpdate(elapsedTime);
        camera->setViewportSize(size.width(), size.height());
        camera->renderUpdate();
        view->options().targetFrameBuffer = gl->defaultFramebufferObject();
        view->options().width = size.width();
        view->options().height = size.height();
        view->render();
#ifdef NDEBUG
    }
    catch(...)
    {

        this->close();
        return;
    }
#endif

    // finish the frame
    gl->swapBuffers(this->context()->surface());

}

my widget hpp

#ifndef VTSWIDGET_H
#define VTSWIDGET_H

#include <QOpenGLWidget>
#include <memory>
#include <chrono>
#include <QWindow>
#include <QThread>
#include <QOpenGLContext>
#include <QSurface>
#include <QOpenGLFunctions>
namespace vts
{
    class Map;
    class Camera;
    class Navigation;

    namespace renderer
    {
        class RenderContext;
        class RenderView;
    }
}

class Gl : public QOpenGLContext
{
public:
    explicit Gl(QSurface *surface);

    void initialize();
    void current(bool bind = true);

    QSurface *surface;
};

class DataThread : public QThread
{
public:
    std::shared_ptr<Gl> gl;
    std::shared_ptr<vts::Map> map;

    void run() override;
};


class VtsWidget : public QOpenGLWidget, protected QOpenGLFunctions
{
public:
    explicit VtsWidget(QWidget *parent = nullptr);
    ~VtsWidget();
    void initializeGL() override;
    bool event(QEvent *event);
    void paintGL() override;

    void mouseMove(class QMouseEvent *event);
    void mousePress(class QMouseEvent *event);
    void mouseRelease(class QMouseEvent *event);
    void mouseWheel(class QWheelEvent *event);

    std::shared_ptr<Gl> gl;
    std::shared_ptr<vts::renderer::RenderContext> vtscontext;
    std::shared_ptr<vts::Map> map;
    std::shared_ptr<vts::Camera> camera;
    std::shared_ptr<vts::Navigation> navigation;
    std::shared_ptr<vts::renderer::RenderView> view;

    QPoint lastMousePosition;
    std::chrono::high_resolution_clock::time_point lastTime;

    DataThread dataThread;
private:
};

#endif // VTSWIDGET_H

and my main

#include <QApplication>


#include "vtswidget.h"
int main(int argc, char *argv[])
{
    QApplication::setAttribute(Qt::AA_UseDesktopOpenGL);
    QApplication app(argc, argv);
    std::setlocale(LC_ALL, "C");

      VtsWidget glWidget;
      glWidget.show();

      // Clean up the global context
     // globalContext->doneCurrent();
     // delete globalContext;


    return app.exec();
}

I tried debugging the context, but evertyhing seems normal. I also tried debugging the vts functions i'm using but nothing succeed. I'm lacking experience in QT so maybe someone could help me. In order to test this on your local machine you need to follow the building.md file of the linked git and replace what is in the browser/src/vts-browser-qt and modify the cmakelist in consequence. I'm trying to do this on a Ubuntu 20.04. Thanks in advance for any help or returns.

1

There are 1 best solutions below

1
On

Maybe your app call paintGL() function only once at start up? When I was doing my QT5 app with QOpenGLWidget, I ran into the same problem(I hope it is the same as mine). I guess, your app is just don't call update() function, which, then, calls paintGL().

Try this snipped at widget initialization in function initializeGL():

QTimer* Timer = new QTimer(this);
connect(Timer, SIGNAL(timeout()), this, SLOT(update()));
Timer->start(1000/33);

Hope that will help