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_Scene.h : manage scene data and OpenGL render pipelines 
0004 ===============================================================
0005 
0006 Primary members
0007 -----------------
0008 
0009 (SScene)sc
0010     source of SMesh data  
0011 (SGLM)gm
0012      view/projection maths using glm 
0013 (SGLFW)gl
0014      OpenGL render top level 
0015 
0016 
0017 SGLFW_Program render pipelines
0018 --------------------------------
0019 
0020 wire
0021     wireframe
0022 iwire
0023     instanced wireframe
0024 norm
0025     normal shader
0026 inorm
0027     instanced normal shader
0028 
0029 
0030 **/
0031 
0032 #include "SScene.h"
0033 #include "SGLFW.h"
0034 
0035 struct SGLFW_Scene
0036 {
0037     static constexpr const char* _DUMP = "SGLFW_Scene__DUMP" ; 
0038     bool            DUMP ; 
0039     
0040     SGLFW&        gl ; 
0041     SGLM&         gm ; 
0042 
0043     const char* shader_fold ;
0044     SGLFW_Program* wire ; 
0045     SGLFW_Program* iwire ;
0046     SGLFW_Program* norm ; 
0047     SGLFW_Program* inorm ;
0048 
0049     std::vector<SGLFW_Mesh*> mesh ; 
0050 
0051     SGLFW_Scene(SGLFW& gl ); 
0052     void init(); 
0053     void initProg(); 
0054     void initMesh(); 
0055 
0056     SGLFW_Program* getIProg() const ; 
0057     SGLFW_Program* getProg() const ; 
0058 
0059     void render(); 
0060     void renderloop(); 
0061 }; 
0062 
0063 
0064 
0065 inline SGLFW_Program* SGLFW_Scene::getIProg() const 
0066 {
0067     return gm.toggle.norm ? inorm : iwire ;  
0068 }
0069 inline SGLFW_Program* SGLFW_Scene::getProg() const 
0070 {
0071     return gm.toggle.norm ? norm : wire ;  
0072 }
0073 
0074 
0075 inline SGLFW_Scene::SGLFW_Scene(SGLFW& _gl)
0076     :
0077     DUMP(ssys::getenvbool(_DUMP)), 
0078     gl(_gl),
0079     gm(gl.gm),
0080     shader_fold("${SGLFW_Scene__shader_fold:-$OPTICKS_PREFIX/gl}"),
0081     wire(nullptr),
0082     iwire(nullptr),
0083     norm(nullptr),
0084     inorm(nullptr)
0085 {
0086     init(); 
0087 }
0088 
0089 inline void SGLFW_Scene::init()
0090 {
0091     initProg();
0092     initMesh();
0093 }
0094 
0095 /**
0096 SGLFW_Scene::initProg
0097 ----------------------
0098 
0099 Create the shaders 
0100 
0101 wire
0102    wireframe
0103 
0104 iwire
0105    instanced wireframe
0106 
0107 norm
0108    normal shader
0109 
0110 inorm
0111    instanced normal shader
0112    
0113 
0114 **/
0115 
0116 inline void SGLFW_Scene::initProg()
0117 {
0118     wire = new SGLFW_Program(spath::Resolve(shader_fold,  "wireframe"), "vPos", "vNrm", nullptr, "MVP", gm.MVP_ptr );
0119     iwire = new SGLFW_Program(spath::Resolve(shader_fold, "iwireframe"), "vPos", "vNrm", "vInstanceTransform", "MVP", gm.MVP_ptr );
0120 
0121     norm = new SGLFW_Program(spath::Resolve(shader_fold, "normal"), "vPos", "vNrm", nullptr, "MVP", gm.MVP_ptr );
0122     inorm = new SGLFW_Program(spath::Resolve(shader_fold, "inormal"), "vPos", "vNrm", "vInstanceTransform", "MVP", gm.MVP_ptr );
0123 }
0124 
0125 /**
0126 SGLFW_Scene::initMesh
0127 -----------------------
0128 
0129 Traverses the meshmerge vector from SScene
0130 passing them to SGLFW_Mesh instances 
0131 which do the OpenGL uploads
0132 
0133 HMM: how to match ray trace IAS/GAS handle selection ?
0134 
0135 **/
0136 
0137 inline void SGLFW_Scene::initMesh()
0138 {
0139     int num_meshmerge = gm.scene->meshmerge.size(); 
0140 
0141     const std::vector<glm::tmat4x4<float>>& inst_tran = gm.scene->inst_tran ; 
0142     const float* values = (const float*)inst_tran.data() ; 
0143     int item_values = 4*4 ; 
0144 
0145     if(DUMP) std::cout 
0146          << "SGLFW_Scene::initMesh"
0147          << " num_meshmerge " << num_meshmerge
0148          << "\n"
0149          ;
0150 
0151     for(int i=0 ; i < num_meshmerge ; i++)
0152     {
0153         const int4&  _inst_info = gm.scene->inst_info[i] ; 
0154 
0155         int num_inst = _inst_info.y ; 
0156         int offset   = _inst_info.z ; 
0157         bool is_instanced = num_inst > 1 ; 
0158 
0159         if(DUMP) std::cout 
0160              << "SGLFW_Scene::initMesh"
0161              << " i " << i
0162              << " num_inst (inst_info.y) " << num_inst
0163              << " offset   (inst_info.z) " << offset 
0164              << " is_instanced " << ( is_instanced ? "YES" : "NO " ) 
0165              << "\n"
0166              ;
0167 
0168         const SMesh* _mm = gm.scene->meshmerge[i] ; 
0169 
0170         SGLFW_Mesh* _mesh = new SGLFW_Mesh(_mm);
0171         if( is_instanced )
0172         {
0173             _mesh->set_inst( num_inst, values + offset*item_values );  
0174             //std::cout << _mesh->desc() << std::endl ; 
0175         }
0176         mesh.push_back(_mesh); 
0177     }
0178 }
0179 
0180 
0181 
0182 /**
0183 SGLFW_Scene::render
0184 --------------------
0185 
0186 TODO: indirect OpenGL to avoid the draw loop 
0187 
0188 Note the draw loop does have the advantage of 
0189 being able to use different shader pipeline 
0190 for different mesh (eg to highlight things). 
0191 
0192 TODO: VIZMASK for flexible skipping 
0193 
0194 **/
0195 
0196 inline void SGLFW_Scene::render()
0197 {
0198     int num_mesh = mesh.size(); 
0199 
0200     if(DUMP) std::cout 
0201          << "SGLFW_Scene::render"
0202          << " num_mesh " << num_mesh
0203          << "\n"
0204          ;
0205 
0206     for(int i=0 ; i < num_mesh ; i++)
0207     {
0208         bool viz = gm.is_vizmask_set(i); 
0209 
0210         if(DUMP) std::cout 
0211              << "SGLFW_Scene::render"
0212              << " i " << i
0213              << " viz " << ( viz ? "YES" : "NO " )
0214              << "\n"
0215              ;
0216 
0217         if(!viz) continue ; 
0218 
0219         SGLFW_Mesh* _mesh = mesh[i] ; 
0220         bool has_inst = _mesh->has_inst() ; 
0221 
0222         if(DUMP) std::cout 
0223              << "SGLFW_Scene::render"
0224              << " i " << i
0225              << " has_inst " << ( has_inst ? "YES" : "NO " )
0226              << "\n"
0227              ;
0228 
0229         SGLFW_Program* _prog = has_inst ? getIProg() : getProg() ;  
0230         _mesh->render(_prog);   
0231     }
0232 }
0233 
0234 
0235 /**
0236 SGLFW_Scene::renderloop
0237 ------------------------
0238 
0239 For ease of integration with alternative renders (eg raytrace)
0240 it is often preferable to directly implement the renderloop
0241 in the main or elsewhere and not use this simple renderloop.
0242 
0243 **/
0244 
0245 inline void SGLFW_Scene::renderloop()
0246 {
0247     while(gl.renderloop_proceed())
0248     {
0249         gl.renderloop_head();  // clears 
0250         render(); 
0251         gl.renderloop_tail();      // swap buffers, poll events
0252     }
0253 }
0254