Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Game Development
  4. Small examples for game development in Qt, OpenGL, Box2D, Bullet Physics, and OpenAL
Forum Updated to NodeBB v4.3 + New Features

Small examples for game development in Qt, OpenGL, Box2D, Bullet Physics, and OpenAL

Scheduled Pinned Locked Moved Game Development
42 Posts 2 Posters 11.8k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • 8 Offline
    8 Offline
    8Observer8
    wrote on 27 May 2024, 14:22 last edited by
    #23

    Custom collision detection between two disks

    WebAssembly demo on free Netlify hosting

    custom-collision-detection-disks-opengles2-qt6-cpp-android.gif

    custom-collision-detection-disks-opengles2-qt6-cpp-desktop.gif

    custom-collision-detection-disks-opengles2-qt6-cpp.pro

    QT += core gui openglwidgets
    
    CONFIG += c++17
    
    SOURCES += \
        main.cpp
    

    main.cpp

    
    #include <QtMath>
    #include <QtGui/QMatrix4x4>
    #include <QtGui/QMouseEvent>
    #include <QtGui/QOpenGLFunctions>
    #include <QtGui/QSurfaceFormat>
    #include <QtGui/QVector3D>
    #include <QtGui/QVector4D>
    #include <QtOpenGL/QOpenGLBuffer>
    #include <QtOpenGL/QOpenGLShader>
    #include <QtOpenGL/QOpenGLShaderProgram>
    #include <QtOpenGL/QOpenGLWindow>
    #include <QtWidgets/QApplication>
    
    class OpenGLWindow : public QOpenGLWindow, private QOpenGLFunctions
    {
    public:
        OpenGLWindow()
        {
            setTitle("OpenGL ES 2.0, Qt6, C++");
            resize(500, 500);
    
            QSurfaceFormat surfaceFormat;
            surfaceFormat.setDepthBufferSize(24);
            surfaceFormat.setSamples(4);
            setFormat(surfaceFormat);
        }
    
        void initializeGL() override
        {
            initializeOpenGLFunctions();
            glClearColor(0.04f, 0.62f, 0.48f, 1.f);
            glEnable(GL_BLEND);
            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    
            QString vertShaderSrc =
                "attribute vec2 aPosition;\n"
                "uniform mat4 uMvpMatrix;"
                "void main()\n"
                "{\n"
                "    gl_Position = uMvpMatrix * vec4(aPosition, 0.0, 1.0);\n"
                "}\n";
    
            QString fragShaderSrc =
                "#ifdef GL_ES\n"
                "precision mediump float;\n"
                "#endif\n"
                "uniform vec4 uColor;\n"
                "void main()\n"
                "{\n"
                "    gl_FragColor = uColor;\n"
                "}\n";
    
            m_program.create();
            m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Vertex, vertShaderSrc);
            m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Fragment, fragShaderSrc);
            m_program.link();
            m_program.bind();
    
            float vertPositions[m_amountOfDiskVertices * 2 + 8]; // Disk + Square
            float radius = 0.5f;
            float angle = 0.f;
    
            int index = 0;
            // Disk center
            vertPositions[index++] = 0.f;
            vertPositions[index++] = 0.f;
    
                   // Disk
            for (int i = 0; i < m_amountOfDiskVertices - 1; i++)
            {
                float radians = qDegreesToRadians(angle);
                float x = radius * qCos(radians);
                float y = radius * qSin(radians);
                vertPositions[index++] = x;
                vertPositions[index++] = y;
                angle += m_angleStep;
            }
            // Square
            vertPositions[index++] = -0.5f;
            vertPositions[index++] = -0.5f;
            vertPositions[index++] = 0.5f;
            vertPositions[index++] = -0.5f;
            vertPositions[index++] = -0.5f;
            vertPositions[index++] = 0.5f;
            vertPositions[index++] = 0.5f;
            vertPositions[index++] = 0.5f;
            m_vertPosBuffer.create();
            m_vertPosBuffer.bind();
            m_vertPosBuffer.allocate(vertPositions, sizeof(vertPositions));
            m_program.setAttributeBuffer("aPosition", GL_FLOAT, 0, 2);
            m_program.enableAttributeArray("aPosition");
    
            m_uColorLocation = m_program.uniformLocation("uColor");
            m_uMvpMatrixLocation = m_program.uniformLocation("uMvpMatrix");
            m_viewMatrix.lookAt(QVector3D(0, 0, 1), QVector3D(0, 0, 0), QVector3D(0, 1, 0));
        }
    
        void resizeGL(int w, int h) override
        {
            int deviceW = w * devicePixelRatio();
            int deviceH = h * devicePixelRatio();
            float deviceAspect = deviceH / (float) deviceW;
    
            if (deviceAspect > m_worldAspect)
            {
                m_viewportWidth = deviceW;
                m_viewportHeight = (int) deviceW * m_worldAspect;
                m_viewportX = 0;
                m_viewportY = (int) (deviceH - m_viewportHeight) / 2.f;
            }
            else
            {
                m_viewportWidth = (int) deviceH / m_worldAspect;
                m_viewportHeight = deviceH;
                m_viewportX = (int) (deviceW - m_viewportWidth) / 2.f;
                m_viewportY = 0;
            }
            m_projMatrix.setToIdentity();
            m_projMatrix.ortho(0.f, m_worldWidth, 0.f, m_worldHeight, 1.f, -1.f);
            m_projViewMatrix = m_projMatrix * m_viewMatrix;
        }
    
        void paintGL() override
        {
            glClear(GL_COLOR_BUFFER_BIT);
            glClearColor(0.2, 0.2, 0.2, 1);
            glClear(GL_COLOR_BUFFER_BIT);
            glViewport(m_viewportX, m_viewportY, m_viewportWidth, m_viewportHeight);
            glScissor(m_viewportX, m_viewportY, m_viewportWidth, m_viewportHeight);
            glClearColor(0.04, 0.62, 0.48, 1);
            glEnable(GL_SCISSOR_TEST);
            glClear(GL_COLOR_BUFFER_BIT);
            glDisable(GL_SCISSOR_TEST);
    
            m_disk2Color.setW(0.2f);
            if (dist(m_disk1PosX, m_disk1PosY, m_disk2PosX, m_disk2PosY) < 30.f)
                m_disk2Color.setW(1.f);
    
            // Disk
            drawDisk(m_disk2PosX, m_disk2PosY, 30.f, m_disk2Color);
            // Disk
            drawDisk(m_disk1PosX, m_disk1PosY, 30.f, QVector4D(0.f, 0.f, 0.5f, 1.f));
            // Left border
            drawRectangle(5.f, 50.f, 5.f, 85.f, 0.f, QVector4D(0.62f, 0.04f, 0.18f, 1.f));
            // Right border
            drawRectangle(195.f, 50.f, 5.f, 85.f, 0.f, QVector4D(0.62f, 0.04f, 0.18f, 1.f));
            // Top border
            drawRectangle(100.f, 95.f, 185.f, 5.f, 0.f, QVector4D(0.62f, 0.04f, 0.18f, 1.f));
            // Bottom border
            drawRectangle(100.f, 5.f, 185.f, 5.f, 0.f, QVector4D(0.62f, 0.04f, 0.18f, 1.f));
        }
    
        float dist(float x1, float y1, float x2, float y2)
        {
            float deltaX = qFabs(x1 - x2);
            float deltaY = qFabs(y1 - y2);
            return qSqrt(qPow(deltaX, 2) + qPow(deltaY, 2));
        }
    
        void drawDisk(float x, float y, float diameter, const QVector4D& color)
        {
            m_modelMatrix.setToIdentity();
            m_modelMatrix.translate(QVector3D(x, y, 0));
            m_modelMatrix.scale(QVector3D(diameter, diameter, 1));
            m_mvpMatrix = m_projViewMatrix * m_modelMatrix;
            m_program.setUniformValue(m_uMvpMatrixLocation, m_mvpMatrix);
            m_program.setUniformValue(m_uColorLocation, color);
            glDrawArrays(GL_TRIANGLE_FAN, 0, m_amountOfDiskVertices);
        }
    
        void drawRectangle(float x, float y, float w, float h,
            float angle, const QVector4D& color)
        {
            m_modelMatrix.setToIdentity();
            m_modelMatrix.translate(QVector3D(x, y, 0));
            m_modelMatrix.rotate(angle, QVector3D(0, 0, 1));
            m_modelMatrix.scale(QVector3D(w, h, 1));
            m_mvpMatrix = m_projViewMatrix * m_modelMatrix;
            m_program.setUniformValue(m_uMvpMatrixLocation, m_mvpMatrix);
            m_program.setUniformValue(m_uColorLocation, color);
            glDrawArrays(GL_TRIANGLE_STRIP, m_amountOfDiskVertices, 4);
        }
    
        void mousePressEvent(QMouseEvent *event) override
        {
            switch (event->button()) {
                case Qt::MouseButton::LeftButton:
                {
                    m_mouseHolding = true;
                    int x = event->pos().x() * devicePixelRatio();
                    int y = (height() - event->pos().y() - 1) * devicePixelRatio();
                    if ((m_viewportX <= x && x < (m_viewportX + m_viewportWidth)) &&
                        (m_viewportY <= y && y < (m_viewportY + m_viewportHeight)))
                    {
                        float normalizedX = (x - m_viewportX) / (float) m_viewportWidth;
                        float normalizedY = (y - m_viewportY) / (float) m_viewportHeight;
                        m_disk1PosX = m_worldWidth * normalizedX;
                        m_disk1PosY = m_worldHeight * normalizedY;
                    }
                    update();
                    break;
                }
                default:
                    break;
            }
        }
    
        void mouseMoveEvent(QMouseEvent *event) override
        {
            if (!m_mouseHolding)
                return;
    
            int x = event->pos().x() * devicePixelRatio();
            int y = (height() - event->pos().y() - 1) * devicePixelRatio();
            if ((m_viewportX <= x && x < (m_viewportX + m_viewportWidth)) &&
                (m_viewportY <= y && y < (m_viewportY + m_viewportHeight)))
            {
                float normalizedX = (x - m_viewportX) / (float) m_viewportWidth;
                float normalizedY = (y - m_viewportY) / (float) m_viewportHeight;
                m_disk1PosX = m_worldWidth * normalizedX;
                m_disk1PosY = m_worldHeight * normalizedY;
            }
            update();
        }
    
        void mouseReleaseEvent(QMouseEvent *event) override
        {
            switch (event->button()) {
                case Qt::MouseButton::LeftButton:
                {
                    m_mouseHolding = false;
                    break;
                }
                default:
                    break;
            }
        }
    
    private:
        QOpenGLBuffer m_vertPosBuffer;
        QOpenGLShaderProgram m_program;
        int m_uColorLocation;
        int m_uMvpMatrixLocation;
        QMatrix4x4 m_mvpMatrix;
        QMatrix4x4 m_projMatrix;
        QMatrix4x4 m_viewMatrix;
        QMatrix4x4 m_projViewMatrix;
        QMatrix4x4 m_modelMatrix;
        const float m_worldWidth = 200.f;
        const float m_worldHeight = 100.f;
        float m_worldAspect = m_worldHeight / m_worldWidth;
        int m_viewportX;
        int m_viewportY;
        int m_viewportWidth;
        int m_viewportHeight;
        float m_angleStep = 10.f;
        int m_amountOfDiskVertices = 360.f / m_angleStep + 2;
        bool m_mouseHolding = false;
        float m_disk1PosX = 150.f;
        float m_disk1PosY = 50.f;
        QVector4D m_disk2Color = QVector4D(0.8f, 0.f, 0.f, 0.2f);
        float m_disk2PosX = 70.f;
        float m_disk2PosY = 50.f;
    };
    
    int main(int argc, char *argv[])
    {
        QApplication::setAttribute(Qt::ApplicationAttribute::AA_UseDesktopOpenGL);
        QApplication app(argc, argv);
        OpenGLWindow w;
        w.show();
        return app.exec();
    }
    1 Reply Last reply
    0
    • 8 Offline
      8 Offline
      8Observer8
      wrote on 27 May 2024, 17:07 last edited by 8Observer8
      #24

      Lines with thickness with disks between them

      This example draws two lines from "start" to "finish" with thickness:

      void drawLine(const QVector2D &from, const QVector2D &to, float thickness,
          const QVector3D& color)
      

      It draws a rectangle. I place three disks: in the start point, between lines (where lines are connected), and in the finish point:

              // Strip line
              // Disk
              QVector3D lineColor(0.25f, 0.31f, 0.85f);
              drawDisk(20.f, 50.f, 10.f, lineColor);
              // Line
              drawLine(QVector2D(20.f, 50.f), QVector2D(50.f, 70.f), 10.f, lineColor);
              // Disk
              drawDisk(50.f, 70.f, 10.f, lineColor);
              // Line
              drawLine(QVector2D(50.f, 70.f), QVector2D(60.f, 20.f), 10.f, lineColor);
              // Disk
              drawDisk(60.f, 20.f, 10.f, lineColor);
      

      WebAssembly demo on free Netlify hosting

      4432526f-86df-4ca1-be07-343e8c595415-image.png

      7c21b577-d491-4e38-9c6d-26c4d12a73e3-image.png

      lines-with-thickness-opengles2-qt6-cpp.pro

      QT += core gui openglwidgets
      
      CONFIG += c++17
      
      SOURCES += \
          main.cpp
      

      main.cpp

      #include <QtMath>
      #include <QtGui/QMatrix4x4>
      #include <QtGui/QOpenGLFunctions>
      #include <QtGui/QQuaternion>
      #include <QtGui/QSurfaceFormat>
      #include <QtGui/QVector2D>
      #include <QtGui/QVector3D>
      #include <QtOpenGL/QOpenGLBuffer>
      #include <QtOpenGL/QOpenGLShader>
      #include <QtOpenGL/QOpenGLShaderProgram>
      #include <QtOpenGL/QOpenGLWindow>
      #include <QtWidgets/QApplication>
      
      class OpenGLWindow : public QOpenGLWindow, private QOpenGLFunctions
      {
      public:
          OpenGLWindow()
          {
              setTitle("OpenGL ES 2.0, Qt6, C++");
              resize(450, 450);
      
              QSurfaceFormat surfaceFormat;
              surfaceFormat.setDepthBufferSize(24);
              surfaceFormat.setSamples(4);
              setFormat(surfaceFormat);
          }
      
          void initializeGL() override
          {
              initializeOpenGLFunctions();
              glClearColor(0.04f, 0.62f, 0.48f, 1.f);
      
              QString vertShaderSrc =
                  "attribute vec2 aPosition;\n"
                  "uniform mat4 uMvpMatrix;"
                  "void main()\n"
                  "{\n"
                  "    gl_Position = uMvpMatrix * vec4(aPosition, 0.0, 1.0);\n"
                  "}\n";
      
              QString fragShaderSrc =
                  "#ifdef GL_ES\n"
                  "precision mediump float;\n"
                  "#endif\n"
                  "uniform vec3 uColor;\n"
                  "void main()\n"
                  "{\n"
                  "    gl_FragColor = vec4(uColor, 1.0);\n"
                  "}\n";
      
              m_program.create();
              m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Vertex, vertShaderSrc);
              m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Fragment, fragShaderSrc);
              m_program.link();
              m_program.bind();
      
              float vertPositions[m_amountOfDiskVertices * 2 + 8]; // Disk + Square
              float radius = 0.5f;
              float angle = 0.f;
      
              int index = 0;
              // Disk center
              vertPositions[index++] = 0.f;
              vertPositions[index++] = 0.f;
      
              // Disk
              for (int i = 0; i < m_amountOfDiskVertices - 1; i++)
              {
                  float radians = qDegreesToRadians(angle);
                  float x = radius * qCos(radians);
                  float y = radius * qSin(radians);
                  vertPositions[index++] = x;
                  vertPositions[index++] = y;
                  angle += m_angleStep;
              }
              // Square
              vertPositions[index++] = -0.5f;
              vertPositions[index++] = -0.5f;
              vertPositions[index++] = 0.5f;
              vertPositions[index++] = -0.5f;
              vertPositions[index++] = -0.5f;
              vertPositions[index++] = 0.5f;
              vertPositions[index++] = 0.5f;
              vertPositions[index++] = 0.5f;
              m_vertPosBuffer.create();
              m_vertPosBuffer.bind();
              m_vertPosBuffer.allocate(vertPositions, sizeof(vertPositions));
              m_program.setAttributeBuffer("aPosition", GL_FLOAT, 0, 2);
              m_program.enableAttributeArray("aPosition");
      
              m_uColorLocation = m_program.uniformLocation("uColor");
              m_uMvpMatrixLocation = m_program.uniformLocation("uMvpMatrix");
              m_viewMatrix.lookAt(QVector3D(0, 0, 1), QVector3D(0, 0, 0), QVector3D(0, 1, 0));
          }
      
          void resizeGL(int w, int h) override
          {
              int deviceW = w * devicePixelRatio();
              int deviceH = h * devicePixelRatio();
              float deviceAspect = deviceH / (float) deviceW;
      
              if (deviceAspect > m_worldAspect)
              {
                  m_viewportWidth = deviceW;
                  m_viewportHeight = (int) deviceW * m_worldAspect;
                  m_viewportX = 0;
                  m_viewportY = (int) (deviceH - m_viewportHeight) / 2.f;
              }
              else
              {
                  m_viewportWidth = (int) deviceH / m_worldAspect;
                  m_viewportHeight = deviceH;
                  m_viewportX = (int) (deviceW - m_viewportWidth) / 2.f;
                  m_viewportY = 0;
              }
              m_projMatrix.setToIdentity();
              m_projMatrix.ortho(0.f, m_worldWidth, 0.f, m_worldHeight, 1.f, -1.f);
              m_projViewMatrix = m_projMatrix * m_viewMatrix;
          }
      
          void paintGL() override
          {
              glClear(GL_COLOR_BUFFER_BIT);
              glClearColor(0.82f, 0.87f, 0.97f, 1.f);
              glClear(GL_COLOR_BUFFER_BIT);
              glViewport(m_viewportX, m_viewportY, m_viewportWidth, m_viewportHeight);
              glScissor(m_viewportX, m_viewportY, m_viewportWidth, m_viewportHeight);
              glClearColor(0.82f, 0.87f, 0.97f, 1.f);
              glEnable(GL_SCISSOR_TEST);
              glClear(GL_COLOR_BUFFER_BIT);
              glDisable(GL_SCISSOR_TEST);
      
              // Strip line
              // Disk
              QVector3D lineColor(0.25f, 0.31f, 0.85f);
              drawDisk(20.f, 50.f, 10.f, lineColor);
              // Line
              drawLine(QVector2D(20.f, 50.f), QVector2D(50.f, 70.f), 10.f, lineColor);
              // Disk
              drawDisk(50.f, 70.f, 10.f, lineColor);
              // Line
              drawLine(QVector2D(50.f, 70.f), QVector2D(60.f, 20.f), 10.f, lineColor);
              // Disk
              drawDisk(60.f, 20.f, 10.f, lineColor);
      
              // Square
              drawRectangle(100.f, 50.f, 50.f, 50.f, 0.f, QVector3D(0.3f, 0.07f, 0.5f));
              // Disk
              drawDisk(100.f, 50.f, 50.f, QVector3D(0.8f, 0.8f, 0.5f));
      
              // Borders
              QVector3D borderColor(0.62f, 0.04f, 0.18f);
              // Left border
              drawRectangle(5.f, 50.f, 5.f, 85.f, 0.f, borderColor);
              // Right border
              drawRectangle(195.f, 50.f, 5.f, 85.f, 0.f, borderColor);
              // Top border
              drawRectangle(100.f, 95.f, 185.f, 5.f, 0.f, borderColor);
              // Bottom border
              drawRectangle(100.f, 5.f, 185.f, 5.f, 0.f, borderColor);
          }
      
          void drawDisk(float x, float y, float diameter, const QVector3D& color)
          {
              m_modelMatrix.setToIdentity();
              m_modelMatrix.translate(QVector3D(x, y, 0.f));
              m_modelMatrix.scale(QVector3D(diameter, diameter, 1.f));
              m_mvpMatrix = m_projViewMatrix * m_modelMatrix;
              m_program.setUniformValue(m_uMvpMatrixLocation, m_mvpMatrix);
              m_program.setUniformValue(m_uColorLocation, color);
              glDrawArrays(GL_TRIANGLE_FAN, 0, m_amountOfDiskVertices);
          }
      
          void drawRectangle(float x, float y, float w, float h,
              float angle, const QVector3D& color)
          {
              m_modelMatrix.setToIdentity();
              m_modelMatrix.translate(QVector3D(x, y, 0.f));
              m_modelMatrix.rotate(angle, QVector3D(0.f, 0.f, 1.f));
              m_modelMatrix.scale(QVector3D(w, h, 1.f));
              m_mvpMatrix = m_projViewMatrix * m_modelMatrix;
              m_program.setUniformValue(m_uMvpMatrixLocation, m_mvpMatrix);
              m_program.setUniformValue(m_uColorLocation, color);
              glDrawArrays(GL_TRIANGLE_STRIP, m_amountOfDiskVertices, 4);
          }
      
          void drawLine(const QVector2D &from, const QVector2D &to, float thickness,
              const QVector3D& color)
          {
              QVector2D center;
      
              if (from.x() > to.x())
              {
                  center.setX(to.x() + qFabs(from.x() - to.x()) / 2.f);
              }
              else
              {
                  center.setX(from.x() + qFabs(to.x() - from.x()) / 2.f);
              }
      
              if (from.y() > to.y())
              {
                  center.setY(to.y() + qFabs(from.y() - to.y()) / 2.f);
              }
              else
              {
                  center.setY(from.y() + qFabs(to.y() - from.y()) / 2.f);
              }
      
              QVector3D tempVec;
              tempVec.setX(to.x() - from.x());
              tempVec.setY(to.y() - from.y());
              float length = tempVec.length();
              tempVec.normalize();
              QQuaternion quat = QQuaternion::rotationTo(QVector3D(1.f, 0.f, 0.f), tempVec);
      
              m_modelMatrix.setToIdentity();
              m_modelMatrix.translate(QVector3D(center.x(), center.y(), 0.f));
              m_modelMatrix.rotate(quat);
              m_modelMatrix.scale(QVector3D(length, thickness, 1.f));
              m_mvpMatrix = m_projViewMatrix * m_modelMatrix;
              m_program.setUniformValue(m_uMvpMatrixLocation, m_mvpMatrix);
              m_program.setUniformValue(m_uColorLocation, color);
              glDrawArrays(GL_TRIANGLE_STRIP, m_amountOfDiskVertices, 4);
          }
      
      private:
          QOpenGLBuffer m_vertPosBuffer;
          QOpenGLShaderProgram m_program;
          int m_uColorLocation;
          int m_uMvpMatrixLocation;
          QMatrix4x4 m_mvpMatrix;
          QMatrix4x4 m_projMatrix;
          QMatrix4x4 m_viewMatrix;
          QMatrix4x4 m_projViewMatrix;
          QMatrix4x4 m_modelMatrix;
          const float m_worldWidth = 200.f;
          const float m_worldHeight = 100.f;
          float m_worldAspect = m_worldHeight / m_worldWidth;
          int m_viewportX;
          int m_viewportY;
          int m_viewportWidth;
          int m_viewportHeight;
          int m_angleStep = 10;
          int m_amountOfDiskVertices = 360 / m_angleStep + 2;
      };
      
      int main(int argc, char *argv[])
      {
          QApplication::setAttribute(Qt::ApplicationAttribute::AA_UseDesktopOpenGL);
          QApplication app(argc, argv);
          OpenGLWindow w;
          w.show();
          return app.exec();
      }
      
      1 Reply Last reply
      0
      • 8 Offline
        8 Offline
        8Observer8
        wrote on 28 May 2024, 11:23 last edited by 8Observer8
        #25

        Line drawer

        Created a separate class for drawing a line.

        WebAssembly demo on free Netlify hosting

        4a1428fe-c102-448b-acbc-e4a4c9bdaa47-image.png

        662df3bd-205a-4e3e-885b-50ca5700be10-image.png

        line-drawer-opengles2-qt6-cpp.pro

        QT += core gui openglwidgets
        
        win32: LIBS += -lopengl32
        
        CONFIG += c++17
        
        SOURCES += \
            line_drawer.cpp \
            main.cpp \
            opengl_window.cpp
        
        HEADERS += \
            line_drawer.h \
            opengl_window.h
        

        main.cpp

        #include <QtWidgets/QApplication>
        #include "opengl_window.h"
        
        int main(int argc, char *argv[])
        {
            QApplication::setAttribute(Qt::ApplicationAttribute::AA_UseDesktopOpenGL);
            QApplication app(argc, argv);
            OpenGLWindow w;
            w.show();
            return app.exec();
        }
        

        line_drawer.h

        #ifndef LINE_DRAWER
        #define LINE_DRAWER
        
        #include <QtGui/QMatrix4x4>
        #include <QtGui/QVector2D>
        #include <QtGui/QVector3D>
        #include <QtOpenGL/QOpenGLBuffer>
        #include <QtOpenGL/QOpenGLShaderProgram>
        
        class LineDrawer
        {
        public:
            LineDrawer(QOpenGLShaderProgram *program);
        
            void draw(const QVector2D &from, const QVector2D &to,
                const QVector3D &color, float thickness = 1.f);
            void setProjViewMatrix(const QMatrix4x4 &projViewMatrix);
        
        private:
            void bind();
        
        private:
            QOpenGLShaderProgram *m_program;
            QOpenGLBuffer m_vertPosBuffer;
            int m_aPositionLocation;
            int m_uMvpMatrixLocation;
            int m_uColorLocation;
            QMatrix4x4 m_projViewMatrix;
            QMatrix4x4 m_modelMatrix;
            QMatrix4x4 m_mvpMatrix;
        };
        
        #endif // LINE_DRAWER
        

        line_drawer.cpp

        #include "line_drawer.h"
        
        LineDrawer::LineDrawer(QOpenGLShaderProgram *program)
        {
            m_program = program;
            m_program->bind();
        
            m_aPositionLocation = m_program->attributeLocation("aPosition");
            m_uMvpMatrixLocation = m_program->uniformLocation("uMvpMatrix");
            m_uColorLocation = m_program->uniformLocation("uColor");
        
            float vertPositions[] = {
                -0.5, -0.5,
                0.5, -0.5,
                -0.5, 0.5,
                0.5, 0.5
            };
            m_vertPosBuffer.create();
            m_vertPosBuffer.bind();
            m_vertPosBuffer.allocate(vertPositions, sizeof(vertPositions));
        }
        
        void LineDrawer::setProjViewMatrix(const QMatrix4x4 &projViewMatrix)
        {
            m_projViewMatrix = projViewMatrix;
        }
        
        void LineDrawer::bind()
        {
            m_program->bind();
            m_vertPosBuffer.bind();
            m_program->setAttributeBuffer(m_aPositionLocation, GL_FLOAT, 0, 2);
            m_program->enableAttributeArray(m_aPositionLocation);
        }
        
        void LineDrawer::draw(const QVector2D &from, const QVector2D &to,
            const QVector3D &color, float thickness)
        {
            bind();
            float centerX, centerY;
            QVector3D tempVec;
        
            if (from.x() > to.x())
            {
                centerX = to.x() + std::abs(from.x() - to.x()) / 2.f;
            }
            else
            {
                centerX = from.x() + std::abs(to.x() - from.x()) / 2.f;
            }
        
            if (from.y() > to.y())
            {
                centerY = to.y() + std::abs(from.y() - to.y()) / 2.f;
            }
            else
            {
                centerY = from.y() + std::abs(to.y() - from.y()) / 2.f;
            }
        
            tempVec.setX(to.x() - from.x());
            tempVec.setY(to.y() - from.y());
            float length = tempVec.length();
            tempVec.normalize();
            QQuaternion quat = QQuaternion::rotationTo(QVector3D(1, 0, 0), tempVec);
        
            m_modelMatrix.setToIdentity();
            m_modelMatrix.translate(QVector3D(centerX, centerY, 0));
            m_modelMatrix.rotate(quat);
            m_modelMatrix.scale(QVector3D(length, thickness, 1));
            m_mvpMatrix = m_projViewMatrix * m_modelMatrix;
            m_program->setUniformValue(m_uMvpMatrixLocation, m_mvpMatrix);
            m_program->setUniformValue(m_uColorLocation, color);
            glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
        }
        

        opengl_window.h

        #ifndef OPENGL_WINDOW_H
        #define OPENGL_WINDOW_H
        
        #include <QtMath>
        #include <QtGui/QMatrix4x4>
        #include <QtGui/QOpenGLFunctions>
        #include <QtGui/QQuaternion>
        #include <QtGui/QSurfaceFormat>
        #include <QtGui/QVector2D>
        #include <QtGui/QVector3D>
        #include <QtOpenGL/QOpenGLShader>
        #include <QtOpenGL/QOpenGLShaderProgram>
        #include <QtOpenGL/QOpenGLWindow>
        
        #include "line_drawer.h"
        
        class OpenGLWindow : public QOpenGLWindow, private QOpenGLFunctions
        {
        public:
            OpenGLWindow();
        
            ~OpenGLWindow();
        
        private:
            void initializeGL() override;
            void resizeGL(int w, int h) override;
            void paintGL() override;
        
        private:
            QOpenGLShaderProgram m_program;
            QMatrix4x4 m_projMatrix;
            QMatrix4x4 m_viewMatrix;
            QMatrix4x4 m_projViewMatrix;
            const float m_worldWidth = 200.f;
            const float m_worldHeight = 100.f;
            float m_worldAspect = m_worldHeight / m_worldWidth;
            int m_viewportX;
            int m_viewportY;
            int m_viewportWidth;
            int m_viewportHeight;
            LineDrawer *m_lineDrawer;
        };
        
        #endif // OPENGL_WINDOW_H
        

        opengl_window.cpp

        #include "opengl_window.h"
        
        OpenGLWindow::OpenGLWindow()
        {
            setTitle("OpenGL ES 2.0, Qt6, C++");
            resize(450, 450);
        
            QSurfaceFormat surfaceFormat;
            surfaceFormat.setDepthBufferSize(24);
            surfaceFormat.setSamples(4);
            setFormat(surfaceFormat);
        }
        
        OpenGLWindow::~OpenGLWindow()
        {
            delete m_lineDrawer;
        }
        
        void OpenGLWindow::initializeGL()
        {
            initializeOpenGLFunctions();
        
            QString vertShaderSrc =
                "attribute vec2 aPosition;\n"
                "uniform mat4 uMvpMatrix;"
                "void main()\n"
                "{\n"
                "    gl_Position = uMvpMatrix * vec4(aPosition, 0.0, 1.0);\n"
                "}\n";
        
            QString fragShaderSrc =
                "#ifdef GL_ES\n"
                "precision mediump float;\n"
                "#endif\n"
                "uniform vec3 uColor;\n"
                "void main()\n"
                "{\n"
                "    gl_FragColor = vec4(uColor, 1.0);\n"
                "}\n";
        
            m_program.create();
            m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Vertex, vertShaderSrc);
            m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Fragment, fragShaderSrc);
            m_program.link();
            m_program.bind();
        
            m_lineDrawer = new LineDrawer(&m_program);
        
            m_viewMatrix.lookAt(QVector3D(0, 0, 1), QVector3D(0, 0, 0), QVector3D(0, 1, 0));
        }
        
        void OpenGLWindow::resizeGL(int w, int h)
        {
            int deviceW = w * devicePixelRatio();
            int deviceH = h * devicePixelRatio();
            float deviceAspect = deviceH / (float) deviceW;
        
            if (deviceAspect > m_worldAspect)
            {
                m_viewportWidth = deviceW;
                m_viewportHeight = (int) deviceW * m_worldAspect;
                m_viewportX = 0;
                m_viewportY = (int) (deviceH - m_viewportHeight) / 2.f;
            }
            else
            {
                m_viewportWidth = (int) deviceH / m_worldAspect;
                m_viewportHeight = deviceH;
                m_viewportX = (int) (deviceW - m_viewportWidth) / 2.f;
                m_viewportY = 0;
            }
            m_projMatrix.setToIdentity();
            m_projMatrix.ortho(0.f, m_worldWidth, 0.f, m_worldHeight, 1.f, -1.f);
            m_projViewMatrix = m_projMatrix * m_viewMatrix;
        
            m_lineDrawer->setProjViewMatrix(m_projViewMatrix);
        }
        
        void OpenGLWindow::paintGL()
        {
            glClear(GL_COLOR_BUFFER_BIT);
            glClearColor(0.82f, 0.87f, 0.97f, 1.f);
            glClear(GL_COLOR_BUFFER_BIT);
            glViewport(m_viewportX, m_viewportY, m_viewportWidth, m_viewportHeight);
            glScissor(m_viewportX, m_viewportY, m_viewportWidth, m_viewportHeight);
            glClearColor(0.82f, 0.87f, 0.97f, 1.f);
            glEnable(GL_SCISSOR_TEST);
            glClear(GL_COLOR_BUFFER_BIT);
            glDisable(GL_SCISSOR_TEST);
        
            // X axis
            QVector3D xAxisColor(0.80f, 0.15f, 0.18f);
            m_lineDrawer->draw(QVector2D(30.f, 20.f), QVector2D(170.f, 20.f), xAxisColor);
            // Arrow
            m_lineDrawer->draw(QVector2D(165.f, 23.f), QVector2D(170.f, 20.f), xAxisColor);
            m_lineDrawer->draw(QVector2D(165.f, 17.f), QVector2D(170.f, 20.f),xAxisColor);
            // Divisions
            m_lineDrawer->draw(QVector2D(50.f, 17.f), QVector2D(50.f, 23.f), xAxisColor);
            m_lineDrawer->draw(QVector2D(70.f, 17.f), QVector2D(70.f, 23.f), xAxisColor);
            m_lineDrawer->draw(QVector2D(90.f, 17.f), QVector2D(90.f, 23.f), xAxisColor);
            m_lineDrawer->draw(QVector2D(110.f, 17.f), QVector2D(110.f, 23.f), xAxisColor);
            m_lineDrawer->draw(QVector2D(130.f, 17.f), QVector2D(130.f, 23.f), xAxisColor);
            m_lineDrawer->draw(QVector2D(150.f, 17.f), QVector2D(150.f, 23.f), xAxisColor);
        
            // Y axis
            QVector3D yAxisColor(0.20f, 0.60f, 0.30f);
            m_lineDrawer->draw(QVector2D(30.f, 20.f), QVector2D(30.f, 95.f), yAxisColor);
            // Arrow
            m_lineDrawer->draw(QVector2D(27.f, 90.f), QVector2D(30.f, 95.f), yAxisColor);
            m_lineDrawer->draw(QVector2D(33.f, 90.f), QVector2D(30.f, 95.f), yAxisColor);
            // Divisions
            m_lineDrawer->draw(QVector2D(27.f, 40.f), QVector2D(33.f, 40.f), yAxisColor);
            m_lineDrawer->draw(QVector2D(27.f, 60.f), QVector2D(33.f, 60.f), yAxisColor);
            m_lineDrawer->draw(QVector2D(27.f, 80.f), QVector2D(33.f, 80.f), yAxisColor);
        
            // Graph
            QVector3D graphColor(0.25f, 0.31f, 0.85f);
            m_lineDrawer->draw(QVector2D(50.f, 40.f), QVector2D(70.f, 60.f), graphColor);
            m_lineDrawer->draw(QVector2D(70.f, 60.f), QVector2D(130.f, 60.f), graphColor);
            m_lineDrawer->draw(QVector2D(130.f, 60.f), QVector2D(150.f, 80.f), graphColor);
        }
        
        1 Reply Last reply
        0
        • 8 Offline
          8 Offline
          8Observer8
          wrote on 29 May 2024, 08:58 last edited by
          #26

          Rectangle drawer

          WebAssembly demo on free Netlify hosting

          a826ef3c-65a8-4057-8dc6-a9952f09ae7b-image.png

          44977ea3-f4da-492f-a58d-7549b7e21278-image.png

          rectangle-drawer-opengles2-qt6-cpp.pro

          QT += core gui openglwidgets
          
          win32: LIBS += -lopengl32
          
          CONFIG += c++17
          
          SOURCES += \
              main.cpp \
              opengl_window.cpp \
              rectangle_drawer.cpp
          
          HEADERS += \
              opengl_window.h \
              rectangle_drawer.h
          

          main.cpp

          #include <QtWidgets/QApplication>
          #include "opengl_window.h"
          
          int main(int argc, char *argv[])
          {
              QApplication::setAttribute(Qt::ApplicationAttribute::AA_UseDesktopOpenGL);
              QApplication app(argc, argv);
              OpenGLWindow w;
              w.show();
              return app.exec();
          }
          

          rectangle_drawer.h

          #ifndef RECTANGLE_DRAWER
          #define RECTANGLE_DRAWER
          
          #include <QtGui/QMatrix4x4>
          #include <QtGui/QVector2D>
          #include <QtGui/QVector3D>
          #include <QtOpenGL/QOpenGLBuffer>
          #include <QtOpenGL/QOpenGLShaderProgram>
          
          class RectangleDrawer
          {
          public:
              RectangleDrawer(QOpenGLShaderProgram *program);
          
              void draw(const QVector2D &position, const QVector2D &size,
                  const QVector3D &color, float angle = 0.f);
              void setProjViewMatrix(const QMatrix4x4 &projViewMatrix);
          
          private:
              void bind();
          
          private:
              QOpenGLShaderProgram *m_program;
              QOpenGLBuffer m_vertPosBuffer;
              int m_aPositionLocation;
              int m_uMvpMatrixLocation;
              int m_uColorLocation;
              QMatrix4x4 m_projViewMatrix;
              QMatrix4x4 m_modelMatrix;
              QMatrix4x4 m_mvpMatrix;
          };
          
          #endif // RECTANGLE_DRAWER
          

          rectangle_drawer.cpp

          #include "rectangle_drawer.h"
          
          RectangleDrawer::RectangleDrawer(QOpenGLShaderProgram *program)
          {
              m_program = program;
              m_program->bind();
          
              m_aPositionLocation = m_program->attributeLocation("aPosition");
              m_uMvpMatrixLocation = m_program->uniformLocation("uMvpMatrix");
              m_uColorLocation = m_program->uniformLocation("uColor");
          
              float vertPositions[] = {
                  -0.5, -0.5,
                  0.5, -0.5,
                  -0.5, 0.5,
                  0.5, 0.5
              };
              m_vertPosBuffer.create();
              m_vertPosBuffer.bind();
              m_vertPosBuffer.allocate(vertPositions, sizeof(vertPositions));
          }
          
          void RectangleDrawer::setProjViewMatrix(const QMatrix4x4 &projViewMatrix)
          {
              m_projViewMatrix = projViewMatrix;
          }
          
          void RectangleDrawer::bind()
          {
              m_program->bind();
              m_vertPosBuffer.bind();
              m_program->setAttributeBuffer(m_aPositionLocation, GL_FLOAT, 0, 2);
              m_program->enableAttributeArray(m_aPositionLocation);
          }
          
          void RectangleDrawer::draw(const QVector2D &position, const QVector2D &size,
              const QVector3D &color, float angle)
          {
              bind();
              m_modelMatrix.setToIdentity();
              m_modelMatrix.translate(QVector3D(position.x(), position.y(), 0.f));
              m_modelMatrix.rotate(angle, QVector3D(0.f, 0.f, 1.f));
              m_modelMatrix.scale(QVector3D(size.x(), size.y(), 1.f));
              m_mvpMatrix = m_projViewMatrix * m_modelMatrix;
              m_program->setUniformValue(m_uMvpMatrixLocation, m_mvpMatrix);
              m_program->setUniformValue(m_uColorLocation, color);
              glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
          }
          

          opengl_window.h

          #ifndef OPENGL_WINDOW
          #define OPENGL_WINDOW
          
          #include <QtMath>
          #include <QtGui/QMatrix4x4>
          #include <QtGui/QOpenGLFunctions>
          #include <QtGui/QQuaternion>
          #include <QtGui/QSurfaceFormat>
          #include <QtGui/QVector2D>
          #include <QtGui/QVector3D>
          #include <QtOpenGL/QOpenGLShader>
          #include <QtOpenGL/QOpenGLShaderProgram>
          #include <QtOpenGL/QOpenGLWindow>
          
          #include "rectangle_drawer.h"
          
          class OpenGLWindow : public QOpenGLWindow, private QOpenGLFunctions
          {
          public:
              OpenGLWindow();
          
              ~OpenGLWindow();
          
          private:
              void initializeGL() override;
              void resizeGL(int w, int h) override;
              void paintGL() override;
          
          private:
              QOpenGLShaderProgram m_program;
              QMatrix4x4 m_projMatrix;
              QMatrix4x4 m_viewMatrix;
              QMatrix4x4 m_projViewMatrix;
              const float m_worldWidth = 200.f;
              const float m_worldHeight = 100.f;
              float m_worldAspect = m_worldHeight / m_worldWidth;
              int m_viewportX;
              int m_viewportY;
              int m_viewportWidth;
              int m_viewportHeight;
              RectangleDrawer *m_rectangleDrawer;
          };
          
          #endif // OPENGL_WINDOW
          

          opengl_window.cpp

          #include "opengl_window.h"
          
          OpenGLWindow::OpenGLWindow()
          {
              setTitle("OpenGL ES 2.0, Qt6, C++");
              resize(600, 300);
          
              QSurfaceFormat surfaceFormat;
              surfaceFormat.setDepthBufferSize(24);
              surfaceFormat.setSamples(4);
              setFormat(surfaceFormat);
          }
          
          OpenGLWindow::~OpenGLWindow()
          {
              delete m_rectangleDrawer;
          }
          
          void OpenGLWindow::initializeGL()
          {
              initializeOpenGLFunctions();
          
              QString vertShaderSrc =
                  "attribute vec2 aPosition;\n"
                  "uniform mat4 uMvpMatrix;"
                  "void main()\n"
                  "{\n"
                  "    gl_Position = uMvpMatrix * vec4(aPosition, 0.0, 1.0);\n"
                  "}\n";
          
              QString fragShaderSrc =
                  "#ifdef GL_ES\n"
                  "precision mediump float;\n"
                  "#endif\n"
                  "uniform vec3 uColor;\n"
                  "void main()\n"
                  "{\n"
                  "    gl_FragColor = vec4(uColor, 1.0);\n"
                  "}\n";
          
              m_program.create();
              m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Vertex, vertShaderSrc);
              m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Fragment, fragShaderSrc);
              m_program.link();
              m_program.bind();
          
              m_rectangleDrawer = new RectangleDrawer(&m_program);
          
              m_viewMatrix.lookAt(QVector3D(0, 0, 1), QVector3D(0, 0, 0), QVector3D(0, 1, 0));
          }
          
          void OpenGLWindow::resizeGL(int w, int h)
          {
              int deviceW = w * devicePixelRatio();
              int deviceH = h * devicePixelRatio();
              float deviceAspect = deviceH / (float) deviceW;
          
              if (deviceAspect > m_worldAspect)
              {
                  m_viewportWidth = deviceW;
                  m_viewportHeight = (int) deviceW * m_worldAspect;
                  m_viewportX = 0;
                  m_viewportY = (int) (deviceH - m_viewportHeight) / 2.f;
              }
              else
              {
                  m_viewportWidth = (int) deviceH / m_worldAspect;
                  m_viewportHeight = deviceH;
                  m_viewportX = (int) (deviceW - m_viewportWidth) / 2.f;
                  m_viewportY = 0;
              }
              m_projMatrix.setToIdentity();
              m_projMatrix.ortho(0.f, m_worldWidth, 0.f, m_worldHeight, 1.f, -1.f);
              m_projViewMatrix = m_projMatrix * m_viewMatrix;
          
              m_rectangleDrawer->setProjViewMatrix(m_projViewMatrix);
          }
          
          void OpenGLWindow::paintGL()
          {
              glClear(GL_COLOR_BUFFER_BIT);
              glClearColor(0.2f, 0.2f, 0.2f, 1.f);
              // glClearColor(0.82f, 0.87f, 0.97f, 1.f);
              glClear(GL_COLOR_BUFFER_BIT);
              glViewport(m_viewportX, m_viewportY, m_viewportWidth, m_viewportHeight);
              glScissor(m_viewportX, m_viewportY, m_viewportWidth, m_viewportHeight);
              glClearColor(0.82f, 0.87f, 0.97f, 1.f);
              glEnable(GL_SCISSOR_TEST);
              glClear(GL_COLOR_BUFFER_BIT);
              glDisable(GL_SCISSOR_TEST);
          
              m_rectangleDrawer->draw(QVector2D(50.f, 70.f), QVector2D(72.f, 7.f),
                  QVector3D(0.80f, 0.15f, 0.18f), -27.f);
              m_rectangleDrawer->draw(QVector2D(160.f, 50.f), QVector2D(70.f, 5.f),
                  QVector3D(0.20f, 0.60f, 0.30f), 10.f);
              m_rectangleDrawer->draw(QVector2D(100.f, 15.f), QVector2D(150.f, 7.f),
                  QVector3D(0.25f, 0.31f, 0.85f));
          }
          
          1 Reply Last reply
          0
          • 8 Offline
            8 Offline
            8Observer8
            wrote on 29 May 2024, 15:05 last edited by 8Observer8
            #27

            Disk drawer

            WebAssembly demo on free Netlify hosting

            7f948267-de69-476e-93b8-fb71355b3423-image.png

            29f3e494-89c4-4642-9232-5063de0acc78-image.png

            disk-drawer-opengles2-qt6-cpp.pro

            QT += core gui openglwidgets
            
            win32: LIBS += -lopengl32
            
            CONFIG += c++17
            
            SOURCES += \
                disk_drawer.cpp \
                main.cpp \
                opengl_window.cpp
            
            HEADERS += \
                disk_drawer.h \
                opengl_window.h
            

            main.cpp

            #include <QtWidgets/QApplication>
            #include "opengl_window.h"
            
            int main(int argc, char *argv[])
            {
                QApplication::setAttribute(Qt::ApplicationAttribute::AA_UseDesktopOpenGL);
                QApplication app(argc, argv);
                OpenGLWindow w;
                w.show();
                return app.exec();
            }
            

            disk_drawer.h

            #ifndef DISK_DRAWER
            #define DISK_DRAWER
            
            #include <QtGui/QMatrix4x4>
            #include <QtGui/QVector2D>
            #include <QtGui/QVector3D>
            #include <QtOpenGL/QOpenGLBuffer>
            #include <QtOpenGL/QOpenGLShaderProgram>
            
            class DiskDrawer
            {
            public:
                DiskDrawer(QOpenGLShaderProgram *program);
            
                void draw(const QVector2D &position, float diameter,
                    const QVector3D &color);
                void setProjViewMatrix(const QMatrix4x4 &projViewMatrix);
            
            private:
                void bind();
            
            private:
                QOpenGLShaderProgram *m_program;
                QOpenGLBuffer m_vertPosBuffer;
                int m_aPositionLocation;
                int m_uMvpMatrixLocation;
                int m_uColorLocation;
                QMatrix4x4 m_projViewMatrix;
                QMatrix4x4 m_modelMatrix;
                QMatrix4x4 m_mvpMatrix;
                int m_angleStep = 5;
                int m_amountOfDiskVertices = 360 / m_angleStep + 2;
            };
            
            #endif // DISK_DRAWER
            

            disk_drawer.cpp

            #include "disk_drawer.h"
            
            DiskDrawer::DiskDrawer(QOpenGLShaderProgram *program)
            {
                m_program = program;
                m_program->bind();
            
                m_aPositionLocation = m_program->attributeLocation("aPosition");
                m_uMvpMatrixLocation = m_program->uniformLocation("uMvpMatrix");
                m_uColorLocation = m_program->uniformLocation("uColor");
            
                float vertPositions[m_amountOfDiskVertices * 2];
                float radius = 0.5f;
                float angle = 0.f;
                int index = 0;
            
                // Disk center
                vertPositions[index++] = 0.f;
                vertPositions[index++] = 0.f;
            
                for (int i = 0; i < m_amountOfDiskVertices - 1; i++)
                {
                    float radians = qDegreesToRadians(angle);
                    float x = radius * qCos(radians);
                    float y = radius * qSin(radians);
                    vertPositions[index++] = x;
                    vertPositions[index++] = y;
                    angle += m_angleStep;
                }
            
                m_vertPosBuffer.create();
                m_vertPosBuffer.bind();
                m_vertPosBuffer.allocate(vertPositions, sizeof(vertPositions));
            }
            
            void DiskDrawer::setProjViewMatrix(const QMatrix4x4 &projViewMatrix)
            {
                m_projViewMatrix = projViewMatrix;
            }
            
            void DiskDrawer::bind()
            {
                m_program->bind();
                m_vertPosBuffer.bind();
                m_program->setAttributeBuffer(m_aPositionLocation, GL_FLOAT, 0, 2);
                m_program->enableAttributeArray(m_aPositionLocation);
            }
            
            void DiskDrawer::draw(const QVector2D &position, float diameter,
                const QVector3D &color)
            {
                bind();
                m_modelMatrix.setToIdentity();
                m_modelMatrix.translate(QVector3D(position.x(), position.y(), 0.f));
                m_modelMatrix.scale(QVector3D(diameter, diameter, 1.f));
                m_mvpMatrix = m_projViewMatrix * m_modelMatrix;
                m_program->setUniformValue(m_uMvpMatrixLocation, m_mvpMatrix);
                m_program->setUniformValue(m_uColorLocation, color);
                glDrawArrays(GL_TRIANGLE_FAN, 0, m_amountOfDiskVertices);
            }
            

            opengl_window.h

            #ifndef OPENGL_WINDOW
            #define OPENGL_WINDOW
            
            #include <QtMath>
            #include <QtGui/QMatrix4x4>
            #include <QtGui/QOpenGLFunctions>
            #include <QtGui/QQuaternion>
            #include <QtGui/QSurfaceFormat>
            #include <QtGui/QVector2D>
            #include <QtGui/QVector3D>
            #include <QtOpenGL/QOpenGLShader>
            #include <QtOpenGL/QOpenGLShaderProgram>
            #include <QtOpenGL/QOpenGLWindow>
            
            #include "disk_drawer.h"
            
            class OpenGLWindow : public QOpenGLWindow, private QOpenGLFunctions
            {
            public:
                OpenGLWindow();
            
                ~OpenGLWindow();
            
            private:
                void initializeGL() override;
                void resizeGL(int w, int h) override;
                void paintGL() override;
            
            private:
                QOpenGLShaderProgram m_program;
                QMatrix4x4 m_projMatrix;
                QMatrix4x4 m_viewMatrix;
                QMatrix4x4 m_projViewMatrix;
                const float m_worldWidth = 200.f;
                const float m_worldHeight = 100.f;
                float m_worldAspect = m_worldHeight / m_worldWidth;
                int m_viewportX;
                int m_viewportY;
                int m_viewportWidth;
                int m_viewportHeight;
                DiskDrawer *m_diskDrawer;
            };
            
            #endif // OPENGL_WINDOW
            

            opengl_window.cpp

            #include "opengl_window.h"
            
            OpenGLWindow::OpenGLWindow()
            {
                setTitle("OpenGL ES 2.0, Qt6, C++");
                resize(600, 300);
            
                QSurfaceFormat surfaceFormat;
                surfaceFormat.setDepthBufferSize(24);
                surfaceFormat.setSamples(4);
                setFormat(surfaceFormat);
            }
            
            OpenGLWindow::~OpenGLWindow()
            {
                delete m_diskDrawer;
            }
            
            void OpenGLWindow::initializeGL()
            {
                initializeOpenGLFunctions();
            
                QString vertShaderSrc =
                    "attribute vec2 aPosition;\n"
                    "uniform mat4 uMvpMatrix;"
                    "void main()\n"
                    "{\n"
                    "    gl_Position = uMvpMatrix * vec4(aPosition, 0.0, 1.0);\n"
                    "}\n";
            
                QString fragShaderSrc =
                    "#ifdef GL_ES\n"
                    "precision mediump float;\n"
                    "#endif\n"
                    "uniform vec3 uColor;\n"
                    "void main()\n"
                    "{\n"
                    "    gl_FragColor = vec4(uColor, 1.0);\n"
                    "}\n";
            
                m_program.create();
                m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Vertex, vertShaderSrc);
                m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Fragment, fragShaderSrc);
                m_program.link();
                m_program.bind();
            
                m_diskDrawer = new DiskDrawer(&m_program);
            
                m_viewMatrix.lookAt(QVector3D(0, 0, 1), QVector3D(0, 0, 0), QVector3D(0, 1, 0));
            }
            
            void OpenGLWindow::resizeGL(int w, int h)
            {
                int deviceW = w * devicePixelRatio();
                int deviceH = h * devicePixelRatio();
                float deviceAspect = deviceH / (float) deviceW;
            
                if (deviceAspect > m_worldAspect)
                {
                    m_viewportWidth = deviceW;
                    m_viewportHeight = (int) deviceW * m_worldAspect;
                    m_viewportX = 0;
                    m_viewportY = (int) (deviceH - m_viewportHeight) / 2.f;
                }
                else
                {
                    m_viewportWidth = (int) deviceH / m_worldAspect;
                    m_viewportHeight = deviceH;
                    m_viewportX = (int) (deviceW - m_viewportWidth) / 2.f;
                    m_viewportY = 0;
                }
                m_projMatrix.setToIdentity();
                m_projMatrix.ortho(0.f, m_worldWidth, 0.f, m_worldHeight, 1.f, -1.f);
                m_projViewMatrix = m_projMatrix * m_viewMatrix;
            
                m_diskDrawer->setProjViewMatrix(m_projViewMatrix);
            }
            
            void OpenGLWindow::paintGL()
            {
                glClear(GL_COLOR_BUFFER_BIT);
                // glClearColor(0.2f, 0.2f, 0.2f, 1.f);
                glClearColor(0.82f, 0.87f, 0.97f, 1.f);
                glClear(GL_COLOR_BUFFER_BIT);
                glViewport(m_viewportX, m_viewportY, m_viewportWidth, m_viewportHeight);
                glScissor(m_viewportX, m_viewportY, m_viewportWidth, m_viewportHeight);
                glClearColor(0.82f, 0.87f, 0.97f, 1.f);
                glEnable(GL_SCISSOR_TEST);
                glClear(GL_COLOR_BUFFER_BIT);
                glDisable(GL_SCISSOR_TEST);
            
                m_diskDrawer->draw(QVector2D(50.f, 70.f), 40.f,
                    QVector3D(0.80f, 0.15f, 0.18f));
                m_diskDrawer->draw(QVector2D(160.f, 50.f), 50.f,
                    QVector3D(0.20f, 0.60f, 0.30f));
                m_diskDrawer->draw(QVector2D(100.f, 15.f), 20.f,
                    QVector3D(0.25f, 0.31f, 0.85f));
            }
            
            1 Reply Last reply
            0
            • 8 Offline
              8 Offline
              8Observer8
              wrote on 30 May 2024, 09:09 last edited by 8Observer8
              #28

              Ring drawer using line drawer

              The RingDrawer class uses the LineDrawer class to draw the segments of a ring. For example, for number of segments equals to 10:

              void RingDrawer::draw(const QVector2D &center, float radius,
                  const QVector3D &color, int numberOfSegments, float thickness)
              {
                  float angle = 0.f;
                  const float angleStep = 360.f / numberOfSegments;
              
                  float x = radius * qCos(qDegreesToRadians(angle));
                  float y = radius * qSin(qDegreesToRadians(angle));
                  QVector2D from(center.x() + x, center.y() + y);
                  angle += angleStep;
              
                  for (int i = 0; i < numberOfSegments; i++)
                  {
                      x = radius * qCos(qDegreesToRadians(angle));
                      y = radius * qSin(qDegreesToRadians(angle));
                      QVector2D to(center.x() + x, center.y() + y);
                      m_lineDrawer->draw(from, to, color, thickness);
                      angle += angleStep;
                      from = to;
                  }
              }
              

              72b84185-de20-4c48-a487-c69398bae1d2-image.png

              For number of segments equals to 50: WebAssembly demo on free Netlify hosting

              26c86b27-e3fc-4501-987e-e92f21ae14b1-image.png

              61fc9cf8-eebc-48bb-9000-f3c3bc2d16d2-image.png

              ring-drawer-opengles2-qt6-cpp.pro

              QT += core gui openglwidgets
              
              win32: LIBS += -lopengl32
              
              CONFIG += c++17
              
              SOURCES += \
                  line_drawer.cpp \
                  main.cpp \
                  opengl_window.cpp \
                  ring_drawer.cpp
              
              HEADERS += \
                  line_drawer.h \
                  opengl_window.h \
                  ring_drawer.h
              

              main.cpp

              #include <QtWidgets/QApplication>
              #include "opengl_window.h"
              
              int main(int argc, char *argv[])
              {
                  QApplication::setAttribute(Qt::ApplicationAttribute::AA_UseDesktopOpenGL);
                  QApplication app(argc, argv);
                  OpenGLWindow w;
                  w.show();
                  return app.exec();
              }
              

              ring_drawer.h

              #ifndef RING_DRAWER
              #define RING_DRAWER
              
              #include "line_drawer.h"
              
              class RingDrawer
              {
              public:
                  RingDrawer(QOpenGLShaderProgram *program);
                  ~RingDrawer();
              
                  void draw(const QVector2D &center, float radius,
                      const QVector3D &color, int numberOfSegments = 50,
                      float thickness = 1.f);
                  void setProjViewMatrix(const QMatrix4x4 &projViewMatrix);
              
              private:
                  LineDrawer *m_lineDrawer;
              };
              
              #endif // RING_DRAWER
              

              ring_drawer.cpp

              #include <QtMath>
              
              #include "ring_drawer.h"
              
              RingDrawer::RingDrawer(QOpenGLShaderProgram *program)
              {
                  m_lineDrawer = new LineDrawer(program);
              }
              
              RingDrawer::~RingDrawer()
              {
                  delete m_lineDrawer;
              }
              
              void RingDrawer::setProjViewMatrix(const QMatrix4x4 &projViewMatrix)
              {
                  m_lineDrawer->setProjViewMatrix(projViewMatrix);
              }
              
              void RingDrawer::draw(const QVector2D &center, float radius,
                  const QVector3D &color, int numberOfSegments, float thickness)
              {
                  float angle = 0.f;
                  const float angleStep = 360.f / numberOfSegments;
              
                  float x = radius * qCos(qDegreesToRadians(angle));
                  float y = radius * qSin(qDegreesToRadians(angle));
                  QVector2D from(center.x() + x, center.y() + y);
                  angle += angleStep;
              
                  for (int i = 0; i < numberOfSegments; i++)
                  {
                      x = radius * qCos(qDegreesToRadians(angle));
                      y = radius * qSin(qDegreesToRadians(angle));
                      QVector2D to(center.x() + x, center.y() + y);
                      m_lineDrawer->draw(from, to, color, thickness);
                      angle += angleStep;
                      from = to;
                  }
              }
              

              opengl_window.h

              #ifndef OPENGL_WINDOW
              #define OPENGL_WINDOW
              
              #include <QtMath>
              #include <QtGui/QMatrix4x4>
              #include <QtGui/QOpenGLFunctions>
              #include <QtGui/QQuaternion>
              #include <QtGui/QSurfaceFormat>
              #include <QtGui/QVector2D>
              #include <QtGui/QVector3D>
              #include <QtOpenGL/QOpenGLShader>
              #include <QtOpenGL/QOpenGLShaderProgram>
              #include <QtOpenGL/QOpenGLWindow>
              
              #include "ring_drawer.h"
              
              class OpenGLWindow : public QOpenGLWindow, private QOpenGLFunctions
              {
              public:
                  OpenGLWindow();
              
                  ~OpenGLWindow();
              
              private:
                  void initializeGL() override;
                  void resizeGL(int w, int h) override;
                  void paintGL() override;
              
              private:
                  QOpenGLShaderProgram m_program;
                  QMatrix4x4 m_projMatrix;
                  QMatrix4x4 m_viewMatrix;
                  QMatrix4x4 m_projViewMatrix;
                  const float m_worldWidth = 200.f;
                  const float m_worldHeight = 100.f;
                  float m_worldAspect = m_worldHeight / m_worldWidth;
                  int m_viewportX;
                  int m_viewportY;
                  int m_viewportWidth;
                  int m_viewportHeight;
                  RingDrawer *m_ringDrawer;
              };
              
              #endif // OPENGL_WINDOW
              

              opengl_window.cpp

              #include "opengl_window.h"
              
              OpenGLWindow::OpenGLWindow()
              {
                  setTitle("OpenGL ES 2.0, Qt6, C++");
                  resize(600, 300);
              
                  QSurfaceFormat surfaceFormat;
                  surfaceFormat.setDepthBufferSize(24);
                  surfaceFormat.setSamples(4);
                  setFormat(surfaceFormat);
              }
              
              OpenGLWindow::~OpenGLWindow()
              {
                  delete m_ringDrawer;
              }
              
              void OpenGLWindow::initializeGL()
              {
                  initializeOpenGLFunctions();
              
              
                  QString vertShaderSrc =
                      "attribute vec2 aPosition;\n"
                      "uniform mat4 uMvpMatrix;"
                      "void main()\n"
                      "{\n"
                      "    gl_Position = uMvpMatrix * vec4(aPosition, 0.0, 1.0);\n"
                      "}\n";
              
                  QString fragShaderSrc =
                      "#ifdef GL_ES\n"
                      "precision mediump float;\n"
                      "#endif\n"
                      "uniform vec3 uColor;\n"
                      "void main()\n"
                      "{\n"
                      "    gl_FragColor = vec4(uColor, 1.0);\n"
                      "}\n";
              
                  m_program.create();
                  m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Vertex, vertShaderSrc);
                  m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Fragment, fragShaderSrc);
                  m_program.link();
                  m_program.bind();
              
                  m_ringDrawer = new RingDrawer(&m_program);
              
                  m_viewMatrix.lookAt(QVector3D(0, 0, 1), QVector3D(0, 0, 0), QVector3D(0, 1, 0));
              }
              
              void OpenGLWindow::resizeGL(int w, int h)
              {
                  int deviceW = w * devicePixelRatio();
                  int deviceH = h * devicePixelRatio();
                  float deviceAspect = deviceH / (float) deviceW;
              
                  if (deviceAspect > m_worldAspect)
                  {
                      m_viewportWidth = deviceW;
                      m_viewportHeight = (int) deviceW * m_worldAspect;
                      m_viewportX = 0;
                      m_viewportY = (int) (deviceH - m_viewportHeight) / 2.f;
                  }
                  else
                  {
                      m_viewportWidth = (int) deviceH / m_worldAspect;
                      m_viewportHeight = deviceH;
                      m_viewportX = (int) (deviceW - m_viewportWidth) / 2.f;
                      m_viewportY = 0;
                  }
                  m_projMatrix.setToIdentity();
                  m_projMatrix.ortho(0.f, m_worldWidth, 0.f, m_worldHeight, 1.f, -1.f);
                  m_projViewMatrix = m_projMatrix * m_viewMatrix;
              
                  m_ringDrawer->setProjViewMatrix(m_projViewMatrix);
              }
              
              void OpenGLWindow::paintGL()
              {
                  glClear(GL_COLOR_BUFFER_BIT);
                  // glClearColor(0.2f, 0.2f, 0.2f, 1.f);
                  glClearColor(0.82f, 0.87f, 0.97f, 1.f);
                  glClear(GL_COLOR_BUFFER_BIT);
                  glViewport(m_viewportX, m_viewportY, m_viewportWidth, m_viewportHeight);
                  glScissor(m_viewportX, m_viewportY, m_viewportWidth, m_viewportHeight);
                  glClearColor(0.82f, 0.87f, 0.97f, 1.f);
                  glEnable(GL_SCISSOR_TEST);
                  glClear(GL_COLOR_BUFFER_BIT);
                  glDisable(GL_SCISSOR_TEST);
              
                  m_ringDrawer->draw(QVector2D(50.f, 70.f), 20.f,
                      QVector3D(0.80f, 0.15f, 0.18f));
                  m_ringDrawer->draw(QVector2D(160.f, 50.f), 25.f,
                      QVector3D(0.20f, 0.60f, 0.30f));
                  m_ringDrawer->draw(QVector2D(100.f, 15.f), 10.f,
                      QVector3D(0.25f, 0.31f, 0.85f));
              }
              

              line_drawer.h

              #ifndef LINE_DRAWER
              #define LINE_DRAWER
              
              #include <QtGui/QMatrix4x4>
              #include <QtGui/QVector2D>
              #include <QtGui/QVector3D>
              #include <QtOpenGL/QOpenGLBuffer>
              #include <QtOpenGL/QOpenGLShaderProgram>
              
              class LineDrawer
              {
              public:
                  LineDrawer(QOpenGLShaderProgram *program);
              
                  void draw(const QVector2D &from, const QVector2D &to,
                      const QVector3D &color, float thickness = 1.f);
                  void setProjViewMatrix(const QMatrix4x4 &projViewMatrix);
              
              private:
                  void bind();
              
              private:
                  QOpenGLShaderProgram *m_program;
                  QOpenGLBuffer m_vertPosBuffer;
                  int m_aPositionLocation;
                  int m_uMvpMatrixLocation;
                  int m_uColorLocation;
                  QMatrix4x4 m_projViewMatrix;
                  QMatrix4x4 m_modelMatrix;
                  QMatrix4x4 m_mvpMatrix;
              };
              
              #endif // LINE_DRAWER
              

              line_drawer.cpp

              #include "line_drawer.h"
              
              LineDrawer::LineDrawer(QOpenGLShaderProgram *program)
              {
                  m_program = program;
                  m_program->bind();
              
                  m_aPositionLocation = m_program->attributeLocation("aPosition");
                  m_uMvpMatrixLocation = m_program->uniformLocation("uMvpMatrix");
                  m_uColorLocation = m_program->uniformLocation("uColor");
              
                  float vertPositions[] = {
                      -0.5, -0.5,
                      0.5, -0.5,
                      -0.5, 0.5,
                      0.5, 0.5
                  };
                  m_vertPosBuffer.create();
                  m_vertPosBuffer.bind();
                  m_vertPosBuffer.allocate(vertPositions, sizeof(vertPositions));
              }
              
              void LineDrawer::setProjViewMatrix(const QMatrix4x4 &projViewMatrix)
              {
                  m_projViewMatrix = projViewMatrix;
              }
              
              void LineDrawer::bind()
              {
                  m_program->bind();
                  m_vertPosBuffer.bind();
                  m_program->setAttributeBuffer(m_aPositionLocation, GL_FLOAT, 0, 2);
                  m_program->enableAttributeArray(m_aPositionLocation);
              }
              
              void LineDrawer::draw(const QVector2D &from, const QVector2D &to,
                  const QVector3D &color, float thickness)
              {
                  bind();
                  float centerX, centerY;
                  QVector3D tempVec;
              
                  if (from.x() > to.x())
                  {
                      centerX = to.x() + std::abs(from.x() - to.x()) / 2.f;
                  }
                  else
                  {
                      centerX = from.x() + std::abs(to.x() - from.x()) / 2.f;
                  }
              
                  if (from.y() > to.y())
                  {
                      centerY = to.y() + std::abs(from.y() - to.y()) / 2.f;
                  }
                  else
                  {
                      centerY = from.y() + std::abs(to.y() - from.y()) / 2.f;
                  }
              
                  tempVec.setX(to.x() - from.x());
                  tempVec.setY(to.y() - from.y());
                  float length = tempVec.length();
                  tempVec.normalize();
                  QQuaternion quat = QQuaternion::rotationTo(QVector3D(1, 0, 0), tempVec);
              
                  m_modelMatrix.setToIdentity();
                  m_modelMatrix.translate(QVector3D(centerX, centerY, 0));
                  m_modelMatrix.rotate(quat);
                  m_modelMatrix.scale(QVector3D(length, thickness, 1));
                  m_mvpMatrix = m_projViewMatrix * m_modelMatrix;
                  m_program->setUniformValue(m_uMvpMatrixLocation, m_mvpMatrix);
                  m_program->setUniformValue(m_uColorLocation, color);
                  glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
              }
              
              1 Reply Last reply
              0
              • 8 Offline
                8 Offline
                8Observer8
                wrote on 31 May 2024, 16:33 last edited by 8Observer8
                #29

                Orbit controls

                I have created the OrbitControls class to pan a camera with right mouse button, rotate with the left mouse button, and zoom in/out with the wheel:

                WebAssembly demo on free Netlify hosting

                orbit-controls-opengles2-qt6-cpp-desktop.gif

                It is not ready to pan and zoom in/out on Android, rotation only:

                orbit-controls-opengles2-qt6-cpp-android.gif

                Source code for QOpenGLWindow, Qt6, C++

                1 Reply Last reply
                0
                • 8 Offline
                  8 Offline
                  8Observer8
                  wrote on 31 May 2024, 17:13 last edited by
                  #30

                  How to set up Box2D in Qt Creator from sources for build for Android, Desktop, and WebAssembly

                  I have recorded this video today. But I don't like it. The voice is too low. I will make another video later and I will delete this one.

                  https://www.youtube.com/watch?v=OE4OOPQC7Nk

                  1 Reply Last reply
                  0
                  • 8 Offline
                    8 Offline
                    8Observer8
                    wrote on 2 Jun 2024, 11:39 last edited by 8Observer8
                    #31

                    Detecting a mobile browser with Qt WebAssembly (topic)

                    It is important to determine whether a WebAssembly game is running on a mobile device or a personal computer in order to show or hide the joystick.

                    #ifdef Q_OS_WASM
                    #include <emscripten.h>
                    #endif
                    
                    #include "widget.h"
                    
                    #ifdef Q_OS_WASM
                    EM_JS(bool, isMobile, (), {
                        return /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
                    })
                    #endif
                    
                    Widget::Widget(QWidget *parent)
                        : QWidget(parent)
                    {
                        bool isMobile = false;
                    
                    #ifdef Q_OS_WASM
                        isMobile = isMobile();
                    #endif
                    
                    #if defined Q_OS_ANDROID || defined Q_OS_IOS
                        isMobile = true;
                    #endif
                    
                        qDebug() << "isMobile:" << isMobile;
                    }
                    

                    Don't forget to add wasm: here:

                    QT += core gui widgets
                    
                    CONFIG += c++17
                    
                    wasm: INCLUDEPATH += "C:\emsdk\upstream\emscripten\cache\sysroot\include"
                    
                    SOURCES += \
                        main.cpp \
                        widget.cpp
                    
                    HEADERS += \
                        widget.h
                    
                    1 Reply Last reply
                    0
                    • 8 Offline
                      8 Offline
                      8Observer8
                      wrote on 2 Jun 2024, 12:06 last edited by 8Observer8 6 Feb 2024, 12:10
                      #32

                      Get data with Qt client from deployed Node.js server using WebSockets (topic)

                      My following Qt 6.6.3 example works on Android, Desktop, and Web (with Qt WebAssembly). It prints data received from the server. The server contains the Box2D-WASM library. It sends the gravity value in JSON format when a client is connected. It is useful example to make multiplayer games with physics on the server side. I have deployed the example on free Glitch hosting: https://glitch.com/edit/#!/merciful-regal-soursop from the GitHub repository: send-gravity-from-server-to-client-box2d-wasm-js The client contains only one main.cpp file. It outputs the following information to the console:

                      connected
                      "{\"action\":\"scGravity\",\"data\":\"{\\\"x\\\":0,\\\"y\\\":-3}\"}"
                      

                      You should download OpenSSL to run the following example on Android. Open the following window in Qt Creator (Edit > Preferences... > Devices > Android):

                      b861ca0d-d29e-4c0d-8fd7-6e29bcafe64c-image.png

                      Add the following path to your pro-file:

                      QT += core gui websockets widgets
                      
                      android: include(C:/Qt/Tools/OpenSSL-1.1.1j/Win_x64/bin/openssl.pri)
                      
                      CONFIG += c++17
                      
                      SOURCES += \
                          main.cpp
                      

                      Read how to add OpenSSL to your CMake project if you use CMake instead of QMake in the Qt documentaion: Adding OpenSSL Support for Android

                      Build the following example for Android, Desktop, and WebAssembly (I have tested it):

                      main.cpp

                      #include <QtNetwork/QNetworkRequest>
                      #include <QtWebSockets/QWebSocket>
                      #include <QtWidgets/QApplication>
                      #include <QtWidgets/QWidget>
                      
                      class Widget : public QWidget
                      {
                          Q_OBJECT
                      
                      public:
                          Widget()
                          {
                              setWindowTitle("Show gravity from server with Box2D-WASM");
                              resize(420, 200);
                      
                              connect(&m_webSocket, &QWebSocket::connected,
                                  this, &Widget::onConnected);
                              connect(&m_webSocket, &QWebSocket::textMessageReceived,
                                  this, &Widget::onMessageReceived);
                              connect(&m_webSocket, &QWebSocket::errorOccurred,
                                  this, &Widget::onErrorOccurred);
                      
                              QUrl url("wss://merciful-regal-soursop.glitch.me");
                      
                              QNetworkRequest request;
                              request.setUrl(url);
                              request.setRawHeader(QByteArray("User-Agent"),
                                  QByteArray("Mozilla/5.0 "
                                             "(Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
                                             "Chrome/124.0.0.0 Safari/537.36"));
                      
                              m_webSocket.open(request);
                          }
                      
                      private slots:
                      
                          void onConnected()
                          {
                              qDebug() << "connected";
                          }
                          void onMessageReceived(const QString &message)
                          {
                              qDebug() << message;
                          }
                      
                          void onErrorOccurred(QAbstractSocket::SocketError error)
                          {
                              qDebug() << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!";
                              qDebug() << "Error:" << error;
                              qDebug() << "Device supports OpenSSL:" << QSslSocket::supportsSsl();
                              qDebug() << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!";
                          }
                      
                      private:
                          QWebSocket m_webSocket;
                      };
                      
                      #include "main.moc"
                      
                      int main(int argc, char *argv[])
                      {
                          QApplication app(argc, argv);
                          Widget w;
                          w.show();
                          return app.exec();
                      }
                      
                      1 Reply Last reply
                      0
                      • 8 Offline
                        8 Offline
                        8Observer8
                        wrote on 12 Jun 2024, 14:57 last edited by 8Observer8 6 Dec 2024, 20:21
                        #33

                        How to set up PyOpenAL

                        PyOpenAL (released Dec 17, 2019): https://pypi.org/project/PyOpenAL/

                        pip install PyOpenAL

                        You can use original OpenAL API but PyOpenAL has a helpful wrapper functions. If your audio file plays with problems try to open it in the Audacity and export it with Encoding: Signed 16-bit PCM:

                        c07a9d66-47ea-4b65-8aa3-118a493cf312-image.png

                        1 Reply Last reply
                        0
                        • 8 Offline
                          8 Offline
                          8Observer8
                          wrote on 12 Jun 2024, 20:19 last edited by 8Observer8 8 Jun 2024, 12:23
                          #34

                          Play sound by button click with PyOpenAL

                          pip install PyOpenAL PySide6

                          73e73f44-539e-4fba-87f9-82c87287db89-image.png

                          import sys
                          
                          from openal import oalOpen
                          from PySide6.QtWidgets import QApplication, QPushButton, QWidget
                          
                          
                          class Widget(QWidget):
                          
                              def __init__(self):
                                  super().__init__()
                                  self.setWindowTitle("PyOpenAL, PySide6")
                                  self.resize(300, 150)
                          
                                  self.btn = QPushButton("Play Sound", self)
                                  self.btn.clicked.connect(self.onPlay)
                          
                                  self.source = oalOpen("assets/bounce.wav")
                              
                              def onPlay(self):
                                  self.source.play()
                          
                          if __name__ == "__main__":
                              app = QApplication(sys.argv)
                              w = Widget()
                              w.show()
                              sys.exit(app.exec())
                          

                          These are the Audacity settings when exporting an audio file. By default for PyOpenAL it must be "Encoding: Signed 16-bit PCM":

                          8c4c929f-5dfa-45a4-a1ed-14a8bd6f2957-image.png

                          1 Reply Last reply
                          0
                          • 8 Offline
                            8 Offline
                            8Observer8
                            wrote on 12 Jun 2024, 20:20 last edited by 8Observer8 8 Jun 2024, 12:25
                            #35

                            Music volume slider

                            pip install PyOpenAL PySide6

                            ccf148fa-c523-49cb-9330-5cfdbe97003f-image.png

                            The free audio file from itch is used in this example.

                            import sys
                            
                            from openal import oalOpen, oalQuit
                            from PySide6.QtCore import Qt
                            from PySide6.QtWidgets import (QApplication, QCheckBox, QHBoxLayout, QPushButton,
                                                         QSlider, QVBoxLayout, QWidget)
                            
                            
                            class Widget(QWidget):
                            
                                def __init__(self):
                                    super().__init__()
                                    self.setWindowTitle("PyOpenAL, PySide6")
                                    self.resize(300, 150)
                            
                                    # Music check box
                                    playMusic = QCheckBox("Play music")
                                    # playMusic.toggle()
                                    # print(playMusic.isChecked())
                                    playMusic.stateChanged.connect(self.onPlayMusic)
                            
                                    # Sound button
                                    playSoundButton = QPushButton("Play sound")
                                    playSoundButton.clicked.connect(self.onPlaySound)
                            
                                    mousicVolume = 0.1
                            
                                    # Volume slider
                                    volumeSlider = QSlider(Qt.Orientation.Horizontal)
                                    volumeSlider.setValue(int(mousicVolume * 100))
                                    volumeSlider.valueChanged[int].connect(self.onChangeVolume)
                            
                                    self.mousicSource = oalOpen("assets/infant_tour.wav")
                                    self.soundSource = oalOpen("assets/bounce.wav")
                                    self.mousicSource.set_gain(mousicVolume)
                            
                                    self.mousicSource.set_looping(True)
                            
                                    vbox = QVBoxLayout()
                                    vbox.addWidget(volumeSlider)
                                    vbox.addWidget(playMusic)
                                    vbox.addWidget(playSoundButton)
                                    vbox.addStretch(1)
                            
                                    hbox = QHBoxLayout()
                                    hbox.addLayout(vbox)
                                    hbox.addStretch(1)
                                    self.setLayout(hbox)
                            
                                def onPlayMusic(self, state):
                                    
                                    if state == Qt.CheckState.Checked.value:
                                        self.mousicSource.play()
                                    else:
                                        self.mousicSource.pause()
                            
                                def onPlaySound(self):
                                    self.soundSource.play()
                            
                                def onChangeVolume(self, value):
                                    self.mousicSource.set_gain(value / 100)
                            
                                def closeEvent(self, event):
                                    oalQuit()
                            
                            if __name__ == "__main__":
                                app = QApplication(sys.argv)
                                w = Widget()
                                w.show()
                                sys.exit(app.exec())
                            
                            1 Reply Last reply
                            0
                            • 8 Offline
                              8 Offline
                              8Observer8
                              wrote on 13 Jun 2024, 12:37 last edited by 8Observer8
                              #36

                              Custom OpenGL button for WebAssembly and Android

                              You cannot make the standard Qt button for WebAssembly because of this bug: https://bugreports.qt.io/browse/QTBUG-120651 (you can use the patch from the "Gerrit Reviews") But OpenGL allows to make custom GUI elements.

                              WebAssembly demo on free Netlify hosting (QOpenGLWindow)

                              QOpenGLWindow works on Android 7.1.2 in the mobile browser without problems. You can find a lot of GUI game assets on itch: https://itch.io/game-assets/tag-gui I use the following GUI game asset in this demo: https://wenrexa.itch.io/holoui I have used Free Texture Packer to pack to button textures to one texture + json-file. Text was added in GIMP.

                              Source code for Qt6 C++

                              custom-start-button-opengl21-qt6-cpp.gif

                              The same demo for SDL3:

                              Click buttons with color ID using glReadPixels

                              Demo in the browser

                              This example uses the following GUI asset: https://wenrexa.itch.io/holoui. You can find a lot of GUI assets on itch: https://itch.io/game-assets/tag-gui I packed the GUI textures using Free Texture Packer to one texture + JSON. RapidJSON is used to parse the JSON file.

                              Tools: SDL3, Emscripten, C++, CMake, OpenGL ES 2.0, GLM, stb_image, Free Texture Packer, and RapidJSON

                              click-buttons-with-color-id.gif

                              1 Reply Last reply
                              0
                              • 8 Offline
                                8 Offline
                                8Observer8
                                wrote on 15 Jun 2024, 20:11 last edited by 8Observer8
                                #37

                                Activating the discrete GeForce of Radeon video card and OpenGL 3.3 Core profile on laptops

                                You can make it with the following code. The first one is for GeForce. The second one is for Radeon. If you can GeForce the second like with be ignored.

                                #ifdef _WIN32
                                #include <windows.h>
                                extern "C" __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
                                extern "C" __declspec(dllexport) DWORD AmdPowerXpressRequestHighPerformance = 0x00000001;
                                #endif
                                

                                main.cpp

                                #ifdef _WIN32
                                #include <windows.h>
                                extern "C" __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
                                extern "C" __declspec(dllexport) DWORD AmdPowerXpressRequestHighPerformance = 0x00000001;
                                #endif
                                
                                #include <QtGui/QOpenGLContext>
                                #include <QtGui/QOpenGLFunctions>
                                #include <QtGui/QSurfaceFormat>
                                #include <QtWidgets/QApplication>
                                #include <QtOpenGL/QOpenGLWindow>
                                
                                class OpenGLWindow : public QOpenGLWindow, private QOpenGLFunctions
                                {
                                    void initializeGL() override
                                    {
                                        initializeOpenGLFunctions();
                                
                                        qDebug() << "OpenGL version:" << (const char*) glGetString(GL_VERSION);
                                        qDebug() << "GLSL version: " << (const char*) glGetString(GL_SHADING_LANGUAGE_VERSION);
                                        qDebug() << "Vendor: " << (const char*) glGetString(GL_VENDOR);
                                    }
                                };
                                
                                int main(int argc, char *argv[])
                                {
                                    QApplication::setAttribute(Qt::ApplicationAttribute::AA_UseDesktopOpenGL);
                                    QApplication app(argc, argv);
                                    QSurfaceFormat fmt;
                                    fmt.setDepthBufferSize(24);
                                
                                    // Request OpenGL 3.3 core or OpenGL ES 3.0.
                                    if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL)
                                    {
                                        qDebug("Requesting 3.3 core context");
                                        fmt.setVersion(3, 3);
                                        fmt.setProfile(QSurfaceFormat::CoreProfile);
                                    }
                                    else
                                    {
                                        qDebug("Requesting 3.0 context");
                                        fmt.setVersion(3, 0);
                                    }
                                
                                    OpenGLWindow w;
                                    w.setFormat(fmt);
                                    w.show();
                                    return app.exec();
                                }
                                

                                Output:

                                Requesting 3.3 core context
                                OpenGL version: 3.3.0 NVIDIA 391.35
                                GLSL version:  3.30 NVIDIA via Cg compiler
                                Vendor:  NVIDIA Corporation
                                

                                By default the laptops with two video cards use the integrated video card:

                                main.cpp

                                #include <QtGui/QOpenGLContext>
                                #include <QtGui/QOpenGLFunctions>
                                #include <QtGui/QSurfaceFormat>
                                #include <QtWidgets/QApplication>
                                #include <QtOpenGL/QOpenGLWindow>
                                
                                class OpenGLWindow : public QOpenGLWindow, private QOpenGLFunctions
                                {
                                    void initializeGL() override
                                    {
                                        initializeOpenGLFunctions();
                                
                                        qDebug() << "OpenGL version:" << (const char*) glGetString(GL_VERSION);
                                        qDebug() << "GLSL version: " << (const char*) glGetString(GL_SHADING_LANGUAGE_VERSION);
                                        qDebug() << "Vendor: " << (const char*) glGetString(GL_VENDOR);
                                    }
                                };
                                
                                int main(int argc, char *argv[])
                                {
                                    QApplication::setAttribute(Qt::ApplicationAttribute::AA_UseDesktopOpenGL);
                                    QApplication app(argc, argv);
                                    QSurfaceFormat fmt;
                                    fmt.setDepthBufferSize(24);
                                
                                    // Request OpenGL 3.3 core or OpenGL ES 3.0.
                                    if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL)
                                    {
                                        qDebug("Requesting 3.3 core context");
                                        fmt.setVersion(3, 3);
                                        fmt.setProfile(QSurfaceFormat::CoreProfile);
                                    }
                                    else
                                    {
                                        qDebug("Requesting 3.0 context");
                                        fmt.setVersion(3, 0);
                                    }
                                
                                    OpenGLWindow w;
                                    w.setFormat(fmt);
                                    w.show();
                                    return app.exec();
                                }
                                

                                Output:

                                Requesting 3.3 core context
                                OpenGL version: 3.1.0 - Build 9.17.10.4459
                                GLSL version:  1.40 - Intel Build 9.17.10.4459
                                Vendor:  Intel
                                
                                1 Reply Last reply
                                0
                                • 8 8Observer8 referenced this topic on 16 Jun 2024, 09:14
                                • 8 Offline
                                  8 Offline
                                  8Observer8
                                  wrote on 17 Jun 2024, 16:37 last edited by 8Observer8 7 Jun 2024, 14:55
                                  #38

                                  Rotate a 3D vector around X, Y, Z axes

                                  In my example, three vectors are rotated 10 degrees around the X, Y and Z axes:

                                  • Rotate the vector (0.f, 0.f, 1.f) 10 degrees around the X axis. Output: (0, -0.173648, 0.984808)
                                  • Rotate the vector (1.f, 0.f, 0.f) 10 degrees around the Y axis. Output: (0.984808, 0, -0.173648)
                                  • Rotate the vector (0.f, 1.f, 0.f) 10 degrees around the Z axis. Output: (-0.173648, 0.984808, 0)
                                  #include <QtGlobal>
                                  #include <QtMath>
                                  #include <QtGui/QOpenGLFunctions>
                                  #include <QtGui/QVector3D>
                                  #include <QtOpenGL/QOpenGLWindow>
                                  #include <QtWidgets/QApplication>
                                  
                                  class OpenGLWindow : public QOpenGLWindow, private QOpenGLFunctions
                                  {
                                      virtual void initializeGL() override
                                      {
                                          initializeOpenGLFunctions();
                                  
                                          // Rotate a 3D vector around the x-axis
                                          QVector3D vector1(0.f, 0.f, 1.f);
                                          QVector3D origin1(0.f, 0.f, 0.f);
                                          float r1 = qDegreesToRadians(10.f);
                                          QVector3D out1 = rotateX(vector1, origin1, r1);
                                          qDebug() << out1;
                                  
                                          // Rotate a 3D vector around the y-axis
                                          QVector3D vector2(1.f, 0.f, 0.f);
                                          QVector3D origin2(0.f, 0.f, 0.f);
                                          float r2 = qDegreesToRadians(10.f);
                                          QVector3D out2 = rotateY(vector2, origin2, r2);
                                          qDebug() << out2;
                                  
                                          // Rotate a 3D vector around the z-axis
                                          QVector3D vector3(0.f, 1.f, 0.f);
                                          QVector3D origin3(0.f, 0.f, 0.f);
                                          float r3 = qDegreesToRadians(10.f);
                                          QVector3D out3 = rotateZ(vector3, origin3, r3);
                                          qDebug() << out3;
                                      }
                                  
                                      QVector3D rotateX(const QVector3D &vector, const QVector3D &origin, float rad)
                                      {
                                          // Translate point to the origin
                                          QVector3D pos;
                                          pos.setX(vector.x() - origin.x());
                                          pos.setY(vector.y() - origin.y());
                                          pos.setZ(vector.z() - origin.z());
                                  
                                          // Perform rotation
                                          QVector3D rot;
                                          rot.setX(pos.x());
                                          rot.setY(pos.y() * qCos(rad) - pos.z() * qSin(rad));
                                          rot.setZ(pos.y() * qSin(rad) + pos.z() * qCos(rad));
                                  
                                          // Translate to correct position
                                          QVector3D out;
                                          out.setX(rot.x() + origin.x());
                                          out.setY(rot.y() + origin.y());
                                          out.setZ(rot.z() + origin.z());
                                  
                                          return out;
                                      }
                                  
                                      QVector3D rotateY(const QVector3D &vector, const QVector3D &origin, float rad)
                                      {
                                          // Translate point to the origin
                                          QVector3D pos;
                                          pos.setX(vector.x() - origin.x());
                                          pos.setY(vector.y() - origin.y());
                                          pos.setZ(vector.z() - origin.z());
                                  
                                          // Perform rotation
                                          QVector3D rot;
                                          rot.setX(pos.z() * qSin(rad) + pos.x() * qCos(rad));
                                          rot.setY(pos.y());
                                          rot.setZ(pos.z() * qCos(rad) - pos.x() * qSin(rad));
                                  
                                          // Translate to correct position
                                          QVector3D out;
                                          out.setX(rot.x() + origin.x());
                                          out.setY(rot.y() + origin.y());
                                          out.setZ(rot.z() + origin.z());
                                  
                                          return out;
                                      }
                                  
                                      QVector3D rotateZ(const QVector3D &vector, const QVector3D &origin, float rad)
                                      {
                                          // Translate point to the origin
                                          QVector3D pos;
                                          pos.setX(vector.x() - origin.x());
                                          pos.setY(vector.y() - origin.y());
                                          pos.setZ(vector.z() - origin.z());
                                  
                                          // Perform rotation
                                          QVector3D rot;
                                          rot.setX(pos.x() * qCos(rad) - pos.y() * qSin(rad));
                                          rot.setY(pos.x() * qSin(rad) + pos.y() * qCos(rad));
                                          rot.setZ(pos.z());
                                  
                                          // Translate to correct position
                                          QVector3D out;
                                          out.setX(rot.x() + origin.x());
                                          out.setY(rot.y() + origin.y());
                                          out.setZ(rot.z() + origin.z());
                                  
                                          return out;
                                      }
                                  };
                                  
                                  int main(int argc, char *argv[])
                                  {
                                      QApplication::setAttribute(Qt::ApplicationAttribute::AA_UseDesktopOpenGL);
                                      QApplication app(argc, argv);
                                      OpenGLWindow w;
                                      w.show();
                                      return app.exec();
                                  }
                                  

                                  pro

                                  QT += core gui openglwidgets
                                  
                                  win32: LIBS += -lopengl32
                                  
                                  CONFIG += c++17
                                  
                                  SOURCES += \
                                      main.cpp
                                  

                                  Source: https://glmatrix.net/docs/vec3.js.html#line564

                                  Using GLM:

                                  // Input vector
                                  auto v = glm::vec3(0.f, 0.f, 1.f);
                                  std::cout << v.x << ", " << v.y << ", " << v.z << std::endl;
                                  // Rotation
                                  auto rotationMatrix = glm::rotate(glm::mat4(1.f), glm::radians(10.f), glm::vec3{1.f, 0.f, 0.f});
                                  auto newVector = rotationMatrix * glm::vec4(v, 0.f);
                                  std::cout << newVector.x << ", " << newVector.y << ", " << newVector.z << std::endl;
                                  // Output: 0, -0.173648, 0.984808
                                  

                                  Stack Oveflow: https://stackoverflow.com/a/78633772/4159530

                                  1 Reply Last reply
                                  0
                                  • 8 Offline
                                    8 Offline
                                    8Observer8
                                    wrote on 2 Jul 2024, 10:10 last edited by 8Observer8 7 Feb 2024, 10:11
                                    #39
                                    This post is deleted!
                                    1 Reply Last reply
                                    0
                                    • 8 Offline
                                      8 Offline
                                      8Observer8
                                      wrote on 18 Jul 2024, 09:31 last edited by 8Observer8
                                      #40

                                      I have found two solutions how I can make the first person movement in the browser. Qt doesn't allow it because it is impossible to call emscripten_request_pointerlock() from Qt application: https://bugreports.qt.io/browse/QTBUG-126513

                                      The first solution is to use pure WebGL and Ammo.js: Click to run a demo in the browser

                                      The second solution is to use SDL3, Emscripten, and Bullet Physics: Click to run a demo in the browser

                                      The demo allows to move with first person and third person view:

                                      image.png

                                      Baked shadows and textures using SDL3, Emscripten, OpenGL ES 2.0, Bullet Physics, and C++

                                      Demo in the browser

                                      5f457ae3-d03b-492f-b513-f540abaec581-image.png

                                      1 Reply Last reply
                                      1
                                      • 8 8Observer8 referenced this topic on 24 Jul 2024, 12:01
                                      • 8 Offline
                                        8 Offline
                                        8Observer8
                                        wrote on 4 Nov 2024, 09:36 last edited by 8Observer8 11 Apr 2024, 09:36
                                        #41

                                        Critical problems for WebAssembly

                                        • Background color of parent window is changed to black: https://bugreports.qt.io/browse/QTBUG-120651
                                        • emscripten_request_pointerlock() returns EMSCRIPTEN_RESULT_UNKNOWN_TARGET: https://bugreports.qt.io/browse/QTBUG-126513
                                        • Dealing with keyboard layout for input on Qt WebAssembly: https://forum.qt.io/post/790688
                                        1 Reply Last reply
                                        0
                                        • 8 Offline
                                          8 Offline
                                          8Observer8
                                          wrote 6 minutes ago last edited by
                                          #42

                                          Transformed triangle in OpenGL 3.3 and Qt 6.9

                                          https://www.youtube.com/watch?v=AGHZsOrazEU

                                          1 Reply Last reply
                                          0

                                          • Login

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular
                                          • Users
                                          • Groups
                                          • Search
                                          • Get Qt Extensions
                                          • Unsolved