LCOV - code coverage report
Current view: top level - ezlibs/ezGL - mesh.hpp (source / functions) Coverage Total Hit
Test: Coverage (llvm-cov → lcov → genhtml) Lines: 0.0 % 185 0
Test Date: 2025-09-16 22:55:37 Functions: 0.0 % 9 0
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : #pragma once
       2                 :             : 
       3                 :             : /*
       4                 :             : MIT License
       5                 :             : 
       6                 :             : Copyright (c) 2014-2024 Stephane Cuillerdier (aka aiekick)
       7                 :             : 
       8                 :             : Permission is hereby granted, free of charge, to any person obtaining a copy
       9                 :             : of this software and associated documentation files (the "Software"), to deal
      10                 :             : in the Software without restriction, including without limitation the rights
      11                 :             : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      12                 :             : copies of the Software, and to permit persons to whom the Software is
      13                 :             : furnished to do so, subject to the following conditions:
      14                 :             : 
      15                 :             : The above copyright notice and this permission notice shall be included in all
      16                 :             : copies or substantial portions of the Software.
      17                 :             : 
      18                 :             : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      19                 :             : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      20                 :             : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      21                 :             : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      22                 :             : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      23                 :             : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      24                 :             : SOFTWARE.
      25                 :             : */
      26                 :             : 
      27                 :             : // ezGL is part of the ezLibs project : https://github.com/aiekick/ezLibs.git
      28                 :             : 
      29                 :             : #include "ezGL.hpp"
      30                 :             : 
      31                 :             : #include <vector>
      32                 :             : #include <memory>
      33                 :             : 
      34                 :             : namespace ez {
      35                 :             : namespace gl {
      36                 :             : 
      37                 :             : template <typename T>
      38                 :             : class Mesh {
      39                 :             : private:
      40                 :             :     std::weak_ptr<Mesh<T>> m_This;
      41                 :             :     GLuint m_VboId = 0U;
      42                 :             :     GLuint m_IboId = 0U;
      43                 :             :     GLuint m_VaoId = 0U;
      44                 :             : 
      45                 :             :     std::vector<T> m_Vertices;
      46                 :             :     std::vector<uint32_t> m_VerticesFormat;
      47                 :             : 
      48                 :             :     std::vector<uint32_t> m_Indices;
      49                 :             : 
      50                 :             :     // MultiDrawwArrays
      51                 :             :     std::vector<GLint> m_IndicesOffsets;
      52                 :             :     std::vector<GLsizei> m_IndicesCounts;
      53                 :             :     GLsizei m_ArraysCount{};
      54                 :             : 
      55                 :             :     bool m_needNewMeshUpload = false;
      56                 :             : 
      57                 :             :     const GLsizei m_VerticeSize = sizeof(T);
      58                 :             :     const GLsizei m_IndiceSize = sizeof(uint32_t);
      59                 :             : 
      60                 :             : public:
      61                 :             :     static std::shared_ptr<Mesh<T>> createStaticDraw(
      62                 :             :         std::vector<T> vVertices,
      63                 :             :         std::vector<uint32_t> vVerticesFormat,
      64                 :             :         std::vector<uint32_t> vIndices = {},
      65                 :             :         std::vector<GLint> vIndicesOffsets = {},
      66                 :             :         std::vector<GLsizei> vIndicesCounts = {},
      67                 :             :         GLsizei vArraysCount = 0) {
      68                 :             :         auto pRet = std::make_shared<Mesh<T>>();
      69                 :             :         pRet->m_This = pRet;
      70                 :             :         if (!pRet->init(vVertices, vVerticesFormat, vIndices, vIndicesOffsets, vIndicesCounts, vArraysCount, true)) {
      71                 :             :             pRet.reset();
      72                 :             :         }
      73                 :             :         return pRet;
      74                 :             :     }
      75                 :             :     static std::shared_ptr<Mesh<T>> createDynamicDraw(
      76                 :             :         std::vector<T> vVertices,
      77                 :             :         std::vector<uint32_t> vVerticesFormat,
      78                 :             :         std::vector<uint32_t> vIndices = {},
      79                 :             :         std::vector<GLint> vIndicesOffsets = {},
      80                 :             :         std::vector<GLsizei> vIndicesCounts = {},
      81                 :             :         GLsizei vArraysCount = 0) {
      82                 :             :         auto pRet = std::make_shared<Mesh<T>>();
      83                 :             :         pRet->m_This = pRet;
      84                 :             :         if (!pRet->init(vVertices, vVerticesFormat, vIndices, vIndicesOffsets, vIndicesCounts, vArraysCount, false)) {
      85                 :             :             pRet.reset();
      86                 :             :         }
      87                 :             :         return pRet;
      88                 :             :     }
      89                 :             : 
      90                 :             : public:
      91                 :             :     Mesh() = default;
      92                 :             :     virtual ~Mesh() { unit(); }
      93                 :             :     uint32_t GetVaoID() { return m_VboId; }
      94                 :             :     uint32_t GetVboID() { return m_IboId; }
      95                 :             :     uint32_t GetIboID() { return m_VaoId; }
      96                 :             :     bool init(
      97                 :             :         std::vector<T> vVertices,
      98                 :             :         std::vector<uint32_t> vVerticesFormat,
      99                 :             :         std::vector<uint32_t> vIndices,
     100                 :             :         std::vector<GLint> vIndicesOffsets,
     101                 :             :         std::vector<GLsizei> vIndicesCounts,
     102                 :             :         GLsizei vArraysCount,
     103                 :           0 :         bool vIsStaticDraw) {
     104                 :           0 :         assert(!vVertices.empty());
     105                 :           0 :         assert(!vVerticesFormat.empty());
     106                 :           0 :         m_Vertices = vVertices;
     107                 :           0 :         m_VerticesFormat = vVerticesFormat;
     108                 :           0 :         m_Indices = vIndices;
     109                 :           0 :         m_IndicesOffsets = vIndicesOffsets;
     110                 :           0 :         m_IndicesCounts = vIndicesCounts;
     111                 :           0 :         m_ArraysCount = vArraysCount;
     112                 :           0 :         glGenVertexArrays(1, &m_VaoId);
     113                 :           0 :         CheckGLErrors;
     114                 :           0 :         glGenBuffers(1, &m_VboId);
     115                 :           0 :         CheckGLErrors;
     116                 :           0 :         if (!m_Indices.empty()) {
     117                 :           0 :             glGenBuffers(1, &m_IboId);
     118                 :           0 :             CheckGLErrors;
     119                 :           0 :         }
     120                 :           0 : 
     121                 :           0 :         // bind
     122                 :           0 :         glBindVertexArray(m_VaoId);
     123                 :           0 :         CheckGLErrors;
     124                 :           0 :         glBindBuffer(GL_ARRAY_BUFFER, m_VboId);
     125                 :           0 :         CheckGLErrors;
     126                 :           0 :         glBufferData(GL_ARRAY_BUFFER, m_VerticeSize * m_Vertices.size(), m_Vertices.data(), vIsStaticDraw ? GL_STATIC_DRAW : GL_DYNAMIC_DRAW);
     127                 :           0 :         CheckGLErrors;
     128                 :           0 : 
     129                 :           0 :         // vertices
     130                 :           0 :         GLuint idx = 0U;
     131                 :           0 :         GLuint offset = 0U;
     132                 :           0 :         for (const auto& format : m_VerticesFormat) {
     133                 :           0 :             assert(format > 0U);
     134                 :           0 :             glEnableVertexAttribArray(idx);
     135                 :           0 :             CheckGLErrors;
     136                 :           0 :             if (idx == 0U) {
     137                 :           0 :                 glVertexAttribPointer(idx, format, GL_FLOAT, GL_FALSE, m_VerticeSize, (void*)nullptr);
     138                 :           0 :             } else {
     139                 :           0 :                 glVertexAttribPointer(idx, format, GL_FLOAT, GL_FALSE, m_VerticeSize, (void*)(sizeof(float) * offset));
     140                 :           0 :             }
     141                 :           0 :             CheckGLErrors;
     142                 :           0 :             glDisableVertexAttribArray(idx);
     143                 :           0 :             CheckGLErrors;
     144                 :           0 :             offset += format;
     145                 :           0 :             ++idx;
     146                 :           0 :         }
     147                 :           0 : 
     148                 :           0 :         // indices
     149                 :           0 :         if (!m_Indices.empty()) {
     150                 :           0 :             glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_IboId);
     151                 :           0 :             CheckGLErrors;
     152                 :           0 :             glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_IndiceSize * m_Indices.size(), m_Indices.data(), GL_STATIC_DRAW);
     153                 :           0 :             CheckGLErrors;
     154                 :           0 :         }
     155                 :           0 : 
     156                 :           0 :         // unbind
     157                 :           0 :         glBindVertexArray(0);
     158                 :           0 :         CheckGLErrors;
     159                 :           0 :         // if i not unbind the VBOs and IBOs after the unbind of the VAO, it seem the VAO is corrupted..
     160                 :           0 :         glBindBuffer(GL_ARRAY_BUFFER, 0);
     161                 :           0 :         CheckGLErrors;
     162                 :           0 :         if (!m_Indices.empty()) {
     163                 :           0 :             glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
     164                 :           0 :             CheckGLErrors;
     165                 :           0 :         }
     166                 :           0 : 
     167                 :           0 :         return (glIsVertexArray(m_VaoId) == GL_TRUE);
     168                 :           0 :     }
     169                 :             : 
     170                 :           0 :     bool bind() {
     171                 :           0 : #ifdef PROFILER_SCOPED
     172                 :           0 :         PROFILER_SCOPED("Mesh", "bin");
     173                 :           0 : #endif
     174                 :           0 :         if (glIsVertexArray(m_VaoId) == GL_TRUE) {
     175                 :           0 :             CheckGLErrors;
     176                 :           0 :             glBindVertexArray(m_VaoId);
     177                 :           0 :             CheckGLErrors;
     178                 :           0 :             for (size_t idx = 0U; idx < m_VerticesFormat.size(); ++idx) {
     179                 :           0 :                 glEnableVertexAttribArray((GLuint)idx);
     180                 :           0 :                 CheckGLErrors;
     181                 :           0 :             }
     182                 :           0 :             return true;
     183                 :           0 :         }
     184                 :           0 :         return false;
     185                 :           0 :     }
     186                 :             : 
     187                 :           0 :     void unbind() {
     188                 :           0 : #ifdef PROFILER_SCOPED
     189                 :           0 :         PROFILER_SCOPED("Mesh", "bin");
     190                 :           0 : #endif
     191                 :           0 :         for (size_t idx = 0U; idx < m_VerticesFormat.size(); ++idx) {
     192                 :           0 :             glDisableVertexAttribArray((GLuint)idx);
     193                 :           0 :             CheckGLErrors;
     194                 :           0 :         }
     195                 :           0 :         glBindVertexArray(0);
     196                 :           0 :     }
     197                 :             : 
     198                 :           0 :     void render(GLenum vRenderMode, const GLsizei vVerticesIdx = 0, const GLsizei vIndicesIdx = 0, const GLsizei vInstanceCount = 0) {
     199                 :           0 : #ifdef PROFILER_SCOPED
     200                 :           0 :         PROFILER_SCOPED("Mesh", "render");
     201                 :           0 : #endif
     202                 :           0 :         m_uploadMeshDatasIfNeeded(vVerticesIdx, vIndicesIdx);
     203                 :           0 :         if (bind()) {
     204                 :           0 :             m_render(vRenderMode, vIndicesIdx, vInstanceCount);
     205                 :           0 :             unbind();
     206                 :           0 :         }
     207                 :           0 :     }
     208                 :             : 
     209                 :           0 :     void unit() {
     210                 :           0 :         if (m_VaoId > 0) {
     211                 :           0 :             glDeleteVertexArrays(1, &m_VaoId);
     212                 :           0 :             CheckGLErrors;
     213                 :           0 :             m_VaoId = 0U;
     214                 :           0 :         }
     215                 :           0 :         if (m_VboId > 0) {
     216                 :           0 :             glDeleteBuffers(1, &m_VboId);
     217                 :           0 :             CheckGLErrors;
     218                 :           0 :             m_VboId = 0U;
     219                 :           0 :         }
     220                 :           0 :         if (m_IboId > 0) {
     221                 :           0 :             glDeleteBuffers(1, &m_IboId);
     222                 :           0 :             CheckGLErrors;
     223                 :           0 :             m_IboId = 0U;
     224                 :           0 :         }
     225                 :           0 :     }
     226                 :             : 
     227                 :             :     std::vector<T> getVertices() const { return m_Vertices; }
     228                 :             : 
     229                 :             :     std::vector<T>& getVerticesRef() { return m_Vertices; }
     230                 :             : 
     231                 :             :     std::vector<uint32_t> getIndices() const { return m_Indices; }
     232                 :             : 
     233                 :             :     std::vector<uint32_t>& getIndicesRef() { return m_Indices; }
     234                 :             : 
     235                 :             :     void needNewUpload() { m_needNewMeshUpload = true; }
     236                 :             : 
     237                 :             : private:
     238                 :           0 :     void m_render(GLenum vRenderMode, const GLsizei vIndicesIdx = 0, const GLsizei vInstanceCount = 0) {
     239                 :           0 :         if (!m_Indices.empty()) {
     240                 :           0 :             if (vInstanceCount > 0) {
     241                 :           0 : #ifdef PROFILER_SCOPED
     242                 :           0 :                 PROFILER_SCOPED("Opengl", "glDrawElementsInstanced");
     243                 :           0 : #endif
     244                 :           0 :                 if (vIndicesIdx == 0) {
     245                 :           0 :                     glDrawElementsInstanced(vRenderMode, (GLsizei)m_Indices.size(), GL_UNSIGNED_INT, nullptr, vInstanceCount);
     246                 :           0 :                 } else {
     247                 :           0 :                     glDrawElementsInstanced(vRenderMode, vIndicesIdx, GL_UNSIGNED_INT, nullptr, vInstanceCount);
     248                 :           0 :                 }
     249                 :           0 :             } else {
     250                 :           0 : #ifdef PROFILER_SCOPED
     251                 :           0 :                 PROFILER_SCOPED("Opengl", "glDrawElements");
     252                 :           0 : #endif
     253                 :           0 :                 if (vIndicesIdx == 0) {
     254                 :           0 :                     glDrawElements(vRenderMode, (GLsizei)m_Indices.size(), GL_UNSIGNED_INT, nullptr);
     255                 :           0 :                 } else {
     256                 :           0 :                     glDrawElements(vRenderMode, vIndicesIdx, GL_UNSIGNED_INT, nullptr);
     257                 :           0 :                 }
     258                 :           0 :             }
     259                 :           0 :         } else if ((!m_IndicesOffsets.empty()) && (!m_IndicesCounts.empty()) && (m_ArraysCount > 0)) {
     260                 :           0 : #ifdef PROFILER_SCOPED
     261                 :           0 :             PROFILER_SCOPED("Opengl", "glMultiDrawArrays");
     262                 :           0 : #endif
     263                 :           0 :             glMultiDrawArrays(vRenderMode, m_IndicesOffsets.data(), m_IndicesCounts.data(), m_ArraysCount);
     264                 :           0 :         } else {
     265                 :           0 : #ifdef PROFILER_SCOPED
     266                 :           0 :             PROFILER_SCOPED("Opengl", "glDrawArrays");
     267                 :           0 : #endif
     268                 :           0 :             glDrawArrays(vRenderMode, 0, GLsizei(m_Vertices.size()));
     269                 :           0 :         }
     270                 :           0 :         CheckGLErrors;
     271                 :           0 :     }
     272                 :           0 :     void m_uploadMeshDatasIfNeeded(const GLsizei vVerticesIdx, const GLsizei vIndicesIdx) {
     273                 :           0 :         if (m_needNewMeshUpload) {
     274                 :           0 :             m_needNewMeshUpload = false;
     275                 :           0 : #ifdef PROFILER_SCOPED
     276                 :           0 :             PROFILER_SCOPED("Opengl", "uploadMeshDatas");
     277                 :           0 : #endif
     278                 :           0 :             // bind
     279                 :           0 :             glBindVertexArray(m_VaoId);
     280                 :           0 :             CheckGLErrors;
     281                 :           0 :             glBindBuffer(GL_ARRAY_BUFFER, m_VboId);
     282                 :           0 :             CheckGLErrors;
     283                 :           0 :             glBufferSubData(GL_ARRAY_BUFFER, 0, m_VerticeSize * vVerticesIdx, m_Vertices.data());
     284                 :           0 :             CheckGLErrors;
     285                 :           0 : 
     286                 :           0 :             // indices
     287                 :           0 :             if (!m_Indices.empty()) {
     288                 :           0 :                 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_IboId);
     289                 :           0 :                 CheckGLErrors;
     290                 :           0 :                 glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, m_IndiceSize * vIndicesIdx, m_Indices.data());
     291                 :           0 :                 CheckGLErrors;
     292                 :           0 :             }
     293                 :           0 : 
     294                 :           0 :             // unbind
     295                 :           0 :             glBindVertexArray(0);
     296                 :           0 :             CheckGLErrors;
     297                 :           0 :             glBindBuffer(GL_ARRAY_BUFFER, 0);
     298                 :           0 :             if (!m_Indices.empty()) {
     299                 :           0 :                 CheckGLErrors;
     300                 :           0 :                 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
     301                 :           0 :             }
     302                 :           0 :         }
     303                 :           0 :     }
     304                 :             : };
     305                 :             : 
     306                 :             : }  // namespace gl
     307                 :             : }  // namespace ez
        

Generated by: LCOV version 2.0-1