Qt 5.11 | Qt Widgets | Boxes | glbuffers.h Example File

Qt 5.11.3 Reference Documentation

# glbuffers.h Example File

graphicsview/boxes/glbuffers.h

      /****************************************************************************
      **
      ** Copyright (C) 2016 The Qt Company Ltd.
      ** Contact: https://www.qt.io/licensing/
      **
      ** This file is part of the demonstration applications of the Qt Toolkit.
      **
      ** $QT_BEGIN_LICENSE:BSD$
      ** Commercial License Usage
      ** Licensees holding valid commercial Qt licenses may use this file in
      ** accordance with the commercial license agreement provided with the
      ** Software or, alternatively, in accordance with the terms contained in
      ** a written agreement between you and The Qt Company. For licensing terms
      ** and conditions see https://www.qt.io/terms-conditions. For further
      ** information use the contact form at https://www.qt.io/contact-us.
      **
      ** BSD License Usage
      ** Alternatively, you may use this file under the terms of the BSD license
      ** as follows:
      **
      ** "Redistribution and use in source and binary forms, with or without
      ** modification, are permitted provided that the following conditions are
      ** met:
      **   * Redistributions of source code must retain the above copyright
      **     notice, this list of conditions and the following disclaimer.
      **   * Redistributions in binary form must reproduce the above copyright
      **     notice, this list of conditions and the following disclaimer in
      **     the documentation and/or other materials provided with the
      **     distribution.
      **   * Neither the name of The Qt Company Ltd nor the names of its
      **     contributors may be used to endorse or promote products derived
      **     from this software without specific prior written permission.
      **
      **
      ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
      ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
      ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
      ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
      **
      ** $QT_END_LICENSE$
      **
      ****************************************************************************/

      #ifndef GLBUFFERS_H
      #define GLBUFFERS_H

      //#include <GL/glew.h>
      #include "glextensions.h"

      #include <QtWidgets>
      #include <QtOpenGL>

      #define BUFFER_OFFSET(i) ((char*)0 + (i))
      #define SIZE_OF_MEMBER(cls, member) sizeof(static_cast<cls *>(0)->member)

      #define GLBUFFERS_ASSERT_OPENGL(prefix, assertion, returnStatement)                         \
      if (m_failed || !(assertion)) {                                                             \
          if (!m_failed) qCritical(prefix ": The necessary OpenGL functions are not available."); \
          m_failed = true;                                                                        \
          returnStatement;                                                                        \
      }

      void qgluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar);

      class QMatrix4x4;

      class GLTexture
      {
      public:
          GLTexture();
          virtual ~GLTexture();
          virtual void bind() = 0;
          virtual void unbind() = 0;
          virtual bool failed() const {return m_failed;}
      protected:
          GLuint m_texture;
          bool m_failed;
      };

      class GLFrameBufferObject
      {
      public:
          friend class GLRenderTargetCube;
          // friend class GLRenderTarget2D;

          GLFrameBufferObject(int width, int height);
          virtual ~GLFrameBufferObject();
          bool isComplete();
          virtual bool failed() const {return m_failed;}
      protected:
          void setAsRenderTarget(bool state = true);
          GLuint m_fbo;
          GLuint m_depthBuffer;
          int m_width, m_height;
          bool m_failed;
      };

      class GLTexture2D : public GLTexture
      {
      public:
          GLTexture2D(int width, int height);
          explicit GLTexture2D(const QString& fileName, int width = 0, int height = 0);
          void load(int width, int height, QRgb *data);
          void bind() override;
          void unbind() override;
      };

      class GLTexture3D : public GLTexture
      {
      public:
          GLTexture3D(int width, int height, int depth);
          // TODO: Implement function below
          //GLTexture3D(const QString& fileName, int width = 0, int height = 0);
          void load(int width, int height, int depth, QRgb *data);
          void bind() override;
          void unbind() override;
      };

      class GLTextureCube : public GLTexture
      {
      public:
          GLTextureCube(int size);
          explicit GLTextureCube(const QStringList& fileNames, int size = 0);
          void load(int size, int face, QRgb *data);
          void bind() override;
          void unbind() override;
      };

      // TODO: Define and implement class below
      //class GLRenderTarget2D : public GLTexture2D

      class GLRenderTargetCube : public GLTextureCube
      {
      public:
          GLRenderTargetCube(int size);
          // begin rendering to one of the cube's faces. 0 <= face < 6
          void begin(int face);
          // end rendering
          void end();
          bool failed() const override { return m_failed || m_fbo.failed(); }

          static void getViewMatrix(QMatrix4x4& mat, int face);
          static void getProjectionMatrix(QMatrix4x4& mat, float nearZ, float farZ);
      private:
          GLFrameBufferObject m_fbo;
      };

      struct VertexDescription
      {
          enum
          {
              Null = 0, // Terminates a VertexDescription array
              Position,
              TexCoord,
              Normal,
              Color,
          };
          int field; // Position, TexCoord, Normal, Color
          int type; // GL_FLOAT, GL_UNSIGNED_BYTE
          int count; // number of elements
          int offset; // field's offset into vertex struct
          int index; // 0 (unused at the moment)
      };

      // Implementation of interleaved buffers.
      // 'T' is a struct which must include a null-terminated static array
      // 'VertexDescription* description'.
      // Example:
      /*
      struct Vertex
      {
          GLfloat position[3];
          GLfloat texCoord[2];
          GLfloat normal[3];
          GLbyte color[4];
          static VertexDescription description[];
      };

      VertexDescription Vertex::description[] = {
          {VertexDescription::Position, GL_FLOAT, SIZE_OF_MEMBER(Vertex, position) / sizeof(GLfloat), offsetof(Vertex, position), 0},
          {VertexDescription::TexCoord, GL_FLOAT, SIZE_OF_MEMBER(Vertex, texCoord) / sizeof(GLfloat), offsetof(Vertex, texCoord), 0},
          {VertexDescription::Normal, GL_FLOAT, SIZE_OF_MEMBER(Vertex, normal) / sizeof(GLfloat), offsetof(Vertex, normal), 0},
          {VertexDescription::Color, GL_BYTE, SIZE_OF_MEMBER(Vertex, color) / sizeof(GLbyte), offsetof(Vertex, color), 0},
          {VertexDescription::Null, 0, 0, 0, 0},
      };
      */
      template<class T>
      class GLVertexBuffer
      {
      public:
          GLVertexBuffer(int length, const T *data = 0, int mode = GL_STATIC_DRAW)
              : m_length(0)
              , m_mode(mode)
              , m_buffer(0)
              , m_failed(false)
          {
              GLBUFFERS_ASSERT_OPENGL("GLVertexBuffer::GLVertexBuffer", glGenBuffers && glBindBuffer && glBufferData, return)

              glGenBuffers(1, &m_buffer);
              glBindBuffer(GL_ARRAY_BUFFER, m_buffer);
              glBufferData(GL_ARRAY_BUFFER, (m_length = length) * sizeof(T), data, mode);
          }

          ~GLVertexBuffer()
          {
              GLBUFFERS_ASSERT_OPENGL("GLVertexBuffer::~GLVertexBuffer", glDeleteBuffers, return)

              glDeleteBuffers(1, &m_buffer);
          }

          void bind()
          {
              GLBUFFERS_ASSERT_OPENGL("GLVertexBuffer::bind", glBindBuffer, return)

              glBindBuffer(GL_ARRAY_BUFFER, m_buffer);
              for (VertexDescription *desc = T::description; desc->field != VertexDescription::Null; ++desc) {
                  switch (desc->field) {
                  case VertexDescription::Position:
                      glVertexPointer(desc->count, desc->type, sizeof(T), BUFFER_OFFSET(desc->offset));
                      glEnableClientState(GL_VERTEX_ARRAY);
                      break;
                  case VertexDescription::TexCoord:
                      glTexCoordPointer(desc->count, desc->type, sizeof(T), BUFFER_OFFSET(desc->offset));
                      glEnableClientState(GL_TEXTURE_COORD_ARRAY);
                      break;
                  case VertexDescription::Normal:
                      glNormalPointer(desc->type, sizeof(T), BUFFER_OFFSET(desc->offset));
                      glEnableClientState(GL_NORMAL_ARRAY);
                      break;
                  case VertexDescription::Color:
                      glColorPointer(desc->count, desc->type, sizeof(T), BUFFER_OFFSET(desc->offset));
                      glEnableClientState(GL_COLOR_ARRAY);
                      break;
                  default:
                      break;
                  }
              }
          }

          void unbind()
          {
              GLBUFFERS_ASSERT_OPENGL("GLVertexBuffer::unbind", glBindBuffer, return)

              glBindBuffer(GL_ARRAY_BUFFER, 0);
              for (VertexDescription *desc = T::description; desc->field != VertexDescription::Null; ++desc) {
                  switch (desc->field) {
                  case VertexDescription::Position:
                      glDisableClientState(GL_VERTEX_ARRAY);
                      break;
                  case VertexDescription::TexCoord:
                      glDisableClientState(GL_TEXTURE_COORD_ARRAY);
                      break;
                  case VertexDescription::Normal:
                      glDisableClientState(GL_NORMAL_ARRAY);
                      break;
                  case VertexDescription::Color:
                      glDisableClientState(GL_COLOR_ARRAY);
                      break;
                  default:
                      break;
                  }
              }
          }

          int length() const {return m_length;}

          T *lock()
          {
              GLBUFFERS_ASSERT_OPENGL("GLVertexBuffer::lock", glBindBuffer && glMapBuffer, return 0)

              glBindBuffer(GL_ARRAY_BUFFER, m_buffer);
              //glBufferData(GL_ARRAY_BUFFER, m_length, NULL, m_mode);
              GLvoid* buffer = glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE);
              m_failed = (buffer == 0);
              return reinterpret_cast<T *>(buffer);
          }

          void unlock()
          {
              GLBUFFERS_ASSERT_OPENGL("GLVertexBuffer::unlock", glBindBuffer && glUnmapBuffer, return)

              glBindBuffer(GL_ARRAY_BUFFER, m_buffer);
              glUnmapBuffer(GL_ARRAY_BUFFER);
          }

          bool failed()
          {
              return m_failed;
          }

      private:
          int m_length, m_mode;
          GLuint m_buffer;
          bool m_failed;
      };

      template<class T>
      class GLIndexBuffer
      {
      public:
          GLIndexBuffer(int length, const T *data = 0, int mode = GL_STATIC_DRAW)
              : m_length(0)
              , m_mode(mode)
              , m_buffer(0)
              , m_failed(false)
          {
              GLBUFFERS_ASSERT_OPENGL("GLIndexBuffer::GLIndexBuffer", glGenBuffers && glBindBuffer && glBufferData, return)

              glGenBuffers(1, &m_buffer);
              glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_buffer);
              glBufferData(GL_ELEMENT_ARRAY_BUFFER, (m_length = length) * sizeof(T), data, mode);
          }

          ~GLIndexBuffer()
          {
              GLBUFFERS_ASSERT_OPENGL("GLIndexBuffer::~GLIndexBuffer", glDeleteBuffers, return)

              glDeleteBuffers(1, &m_buffer);
          }

          void bind()
          {
              GLBUFFERS_ASSERT_OPENGL("GLIndexBuffer::bind", glBindBuffer, return)

              glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_buffer);
          }

          void unbind()
          {
              GLBUFFERS_ASSERT_OPENGL("GLIndexBuffer::unbind", glBindBuffer, return)

              glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
          }

          int length() const {return m_length;}

          T *lock()
          {
              GLBUFFERS_ASSERT_OPENGL("GLIndexBuffer::lock", glBindBuffer && glMapBuffer, return 0)

              glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_buffer);
              GLvoid* buffer = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_READ_WRITE);
              m_failed = (buffer == 0);
              return reinterpret_cast<T *>(buffer);
          }

          void unlock()
          {
              GLBUFFERS_ASSERT_OPENGL("GLIndexBuffer::unlock", glBindBuffer && glUnmapBuffer, return)

              glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_buffer);
              glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
          }

          bool failed()
          {
              return m_failed;
          }

      private:
          int m_length, m_mode;
          GLuint m_buffer;
          bool m_failed;
      };

      #endif