Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-04-09 07:49:38

0001 #pragma once
0002 /**
0003 SGLFW_Mesh.h : create OpenGL buffers with SMesh and instance data and render
0004 ==============================================================================
0005 
0006 Canonical use is from SGLFW_Scene::initMesh
0007 
0008 * (in a former incarnation this was called SGLFW_Render)
0009 
0010 **/
0011 
0012 
0013 struct NP ;
0014 struct SMesh ;
0015 struct SGLFW_Program ;
0016 
0017 
0018 struct SGLFW_Mesh
0019 {
0020     static constexpr const char* _DUMP = "SGLFW_Mesh__DUMP" ;
0021     bool  DUMP ;
0022     const SMesh*   mesh ;
0023 
0024     SGLFW_Buffer*  vtx ;
0025     SGLFW_Buffer*  nrm ;
0026     SGLFW_Buffer*  ins ;
0027 
0028     SGLFW_VAO*     vao ;
0029     SGLFW_Buffer*  idx ;
0030 
0031     int           inst_num ;
0032     const float*  inst_values ;
0033     int           render_count ;
0034 
0035     SGLFW_Mesh(const SMesh* mesh ) ;
0036     void init();
0037 
0038     void set_inst(const NP* _inst );
0039     void set_inst(int _inst_num, const float* _inst_values );
0040     bool has_inst() const ;
0041 
0042     std::string descInst() const ;
0043     std::string desc() const ;
0044 
0045     void render(const SGLFW_Program* prog);
0046     void render_drawElements() const ;
0047 };
0048 
0049 inline SGLFW_Mesh::SGLFW_Mesh(const SMesh* _mesh )
0050     :
0051     DUMP(ssys::getenvbool(_DUMP)),
0052     mesh(_mesh),
0053     vtx(nullptr),
0054     nrm(nullptr),
0055     ins(nullptr),
0056     vao(nullptr),
0057     idx(nullptr),
0058     inst_num(0),
0059     inst_values(nullptr),
0060     render_count(0)
0061 {
0062     init();
0063 }
0064 
0065 /**
0066 SGLFW_Mesh::init
0067 ----------------
0068 
0069 Creates vtx, nrm, idx OpenGL buffers using SGLFW_Buffers
0070 
0071 
0072 **/
0073 
0074 
0075 inline void SGLFW_Mesh::init()
0076 {
0077     vtx = new SGLFW_Buffer( "SGLFW_Mesh.vtx", mesh->vtx->arr_bytes(), mesh->vtx->cvalues<float>(), GL_ARRAY_BUFFER,  GL_STATIC_DRAW );
0078     vtx->bind();
0079     vtx->upload();
0080 
0081     nrm = new SGLFW_Buffer( "SGLFW_Mesh.nrm", mesh->nrm->arr_bytes(), mesh->nrm->cvalues<float>(), GL_ARRAY_BUFFER,  GL_STATIC_DRAW );
0082     nrm->bind();
0083     nrm->upload();
0084 
0085     vao = new SGLFW_VAO("SGLFW_Mesh.vao") ;  // vao: establishes context for OpenGL attrib state and element array (not GL_ARRAY_BUFFER)
0086     vao->bind();
0087 
0088     idx = new SGLFW_Buffer("SGLFW_Mesh.idx", mesh->tri->arr_bytes(), mesh->tri->cvalues<int>()  , GL_ELEMENT_ARRAY_BUFFER, GL_STATIC_DRAW );
0089     idx->bind();
0090     idx->upload();
0091 }
0092 
0093 inline void SGLFW_Mesh::set_inst(const NP* _inst )
0094 {
0095     if(_inst == nullptr) return ;
0096     assert( _inst->uifc == 'f' );
0097     assert( _inst->ebyte == 4 );
0098     assert( _inst->has_shape(-1,4,4));
0099     set_inst( _inst->num_items(), _inst->cvalues<float>() );
0100 }
0101 
0102 inline void SGLFW_Mesh::set_inst(int _inst_num, const float* _inst_values )
0103 {
0104     inst_num = _inst_num ;
0105     inst_values = _inst_values ;
0106 
0107     int itemsize = 4*4*sizeof(float) ;
0108     int num_bytes = inst_num*itemsize ;
0109     ins = new SGLFW_Buffer("SGLFW_Mesh.ins", num_bytes, inst_values, GL_ARRAY_BUFFER,  GL_STATIC_DRAW );
0110     ins->bind();
0111     ins->upload();
0112 }
0113 
0114 inline bool SGLFW_Mesh::has_inst() const
0115 {
0116     return inst_num > 0 && inst_values != nullptr ;
0117 }
0118 
0119 
0120 inline std::string SGLFW_Mesh::desc() const
0121 {
0122     std::stringstream ss ;
0123     ss << descInst() ;
0124     std::string str = ss.str() ;
0125     return str ;
0126 }
0127 inline std::string SGLFW_Mesh::descInst() const
0128 {
0129     int edge_items = 10 ;
0130     std::stringstream ss ;
0131     ss << "[SGLFW_Mesh::descInst inst_num " << inst_num << std::endl ;
0132     ss << stra<float>::DescItems( inst_values, 16, inst_num, edge_items );
0133     ss << "]SGLFW_Mesh::descInst inst_num " << inst_num << std::endl ;
0134     std::string str = ss.str() ;
0135     return str ;
0136 }
0137 
0138 /**
0139 SGLFW_Mesh::render
0140 ---------------------
0141 
0142 Use argument prog to render the mesh
0143 
0144 NB: careful that the intended buffer is bound (making it the active GL_ARRAY_BUFFER)
0145 when the vertex attrib is enabled.  Getting this wrong can for example easily cause
0146 normals to appear in position slots causing perplexing renders.
0147 
0148 **/
0149 
0150 inline void SGLFW_Mesh::render(const SGLFW_Program* prog)
0151 {
0152    prog->use();
0153    vao->bind();
0154 
0155    vtx->bind();
0156    prog->enableVertexAttribArray( prog->vtx_attname, SMesh::VTX_SPEC );
0157 
0158    nrm->bind();
0159    prog->enableVertexAttribArray( prog->nrm_attname, SMesh::NRM_SPEC );
0160 
0161    if(ins)
0162    {
0163        ins->bind();
0164        prog->enableVertexAttribArray_OfTransforms( prog->ins_attname ) ;
0165    }
0166 
0167    idx->bind();
0168    prog->updateMVP();
0169 
0170    render_drawElements();
0171    render_count += 1 ;
0172 }
0173 
0174 inline void SGLFW_Mesh::render_drawElements() const
0175 {
0176     GLenum mode = GL_TRIANGLES ;
0177     GLsizei count = mesh->indices_num() ;  // number of elements to render (eg 3 for 1 triangle)
0178     GLenum type = GL_UNSIGNED_INT ;
0179     const void * indices = (GLvoid*)(sizeof(GLuint) * mesh->indices_offset() ) ;
0180     GLsizei instancecount = ins ? inst_num : 0 ;
0181 
0182     if(instancecount > 0)
0183     {
0184 
0185 #ifdef __APPLE__
0186         glDrawElementsInstanced(mode, count, type, indices, instancecount );
0187         if(DUMP && render_count < 10 ) std::cout
0188             << "SGLFW_Mesh::render_drawElements.glDrawElementsInstanced"
0189             << " render_count " << render_count
0190             << " instancecount " << instancecount
0191             << std::endl
0192             ;
0193 
0194 #else
0195         GLint basevertex = 0 ;
0196         GLuint baseinstance = 0 ;
0197         glDrawElementsInstancedBaseVertexBaseInstance(mode, count, type, indices, instancecount, basevertex, baseinstance );
0198         // SEGV on laptop, OK on workstation
0199         // https://github.com/moderngl/moderngl/issues/346
0200         if(DUMP && render_count < 10 ) std::cout
0201             << "SGLFW_Mesh::render_drawElements.glDrawElementsInstancedBaseVertexBaseInstance"
0202             << " render_count " << render_count
0203             << " instancecount " << instancecount
0204             << std::endl
0205             ;
0206 #endif
0207 
0208     }
0209     else
0210     {
0211         glDrawElements(mode, count, type, indices );
0212     }
0213 }
0214 
0215 
0216