diff --git a/Apps/Examples/extrusionView.cpp b/Apps/Examples/extrusionView.cpp index df6fb7fa155f2152aecb14667a913e2192913e8a..addeaa60dd2720df2995ffef0b4147d4dfd96af1 100644 --- a/Apps/Examples/extrusionView.cpp +++ b/Apps/Examples/extrusionView.cpp @@ -118,7 +118,7 @@ void myGlutWin::init() glClearColor(0.1f,0.1f,0.1f,0.0f); glEnable(GL_DEPTH_TEST); - glEnable(GL_NORMALIZE); +// glEnable(GL_NORMALIZE); glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1); diff --git a/Apps/Tuto/CMakeLists.txt b/Apps/Tuto/CMakeLists.txt index b2b40e226e4bc5608c38cf0317cfb2eac3b6f69a..7d67049e421b32dbcb0aed977a4cfd63d9c1b56b 100644 --- a/Apps/Tuto/CMakeLists.txt +++ b/Apps/Tuto/CMakeLists.txt @@ -61,3 +61,6 @@ add_executable( tuto_ogl3 tuto_ogl3.cpp) target_link_libraries( tuto_ogl3 container topology utils algo ${COMMON_LIBS} ) +add_executable( tuto_ogl2 tuto_ogl2.cpp) +target_link_libraries( tuto_ogl2 + container topology utils algo ${COMMON_LIBS} ) diff --git a/Apps/Tuto/tuto_mt.cpp b/Apps/Tuto/tuto_mt.cpp index fba00a5145eee242d15e98648051f59ce5174e77..4f23cc5aeec8e76c9606b15d736238ceac2c69cc 100644 --- a/Apps/Tuto/tuto_mt.cpp +++ b/Apps/Tuto/tuto_mt.cpp @@ -268,6 +268,14 @@ public: int main(int argc, char **argv) { + + if (argc < 2) + { + std::cerr << argv[0] << " mesh"<< std::endl; + exit(1); + } + + // declaration of the map PFP::MAP myMap; @@ -279,8 +287,7 @@ int main(int argc, char **argv) MyGlutWin mgw(&argc, argv, 800, 800); glewInit(); - // release context (leave it for thread 0); - mgw.releaseContext(); + std::vector attrNames ; if(!Algo::Import::importMesh(myMap, argv[1], attrNames)) @@ -295,8 +302,6 @@ int main(int argc, char **argv) // cree un handler d'attribut pour la position des points (créé lors de l'import) position = myMap.getAttribute(VERTEX_ORBIT, attrNames[0]) ; - - std::cout << "Sommets:"<< position.end()<< std::endl; // cree un handler pour les normales aux sommets AttributeHandler normal = myMap.addAttribute(VERTEX_ORBIT, "normal"); AttributeHandler normal2 = myMap.addAttribute(VERTEX_ORBIT, "normal2"); @@ -332,8 +337,6 @@ int main(int argc, char **argv) std::cout << "length :" < + +#include "Utils/glutwin.h" + +#include "Topology/generic/parameters.h" +#include "Topology/map/map2.h" +#include "Topology/generic/embeddedMap2.h" + + +#include "Algo/Geometry/boundingbox.h" +#include "Algo/Render/vbo_MapRender.h" + +#include "Algo/Modelisation/polyhedron.h" +#include "Geometry/vector_gen.h" +#include "Algo/Geometry/normal.h" + +using namespace CGoGN ; + + +/** + * Struct that contains some informations about the types of the manipulated objects + * Mainly here to be used by the algorithms that are parameterized by it + */ +struct PFP: public PFP_STANDARD +{ + // definition of the type of the map + typedef EmbeddedMap2 MAP; +}; + + +/** + * A class for a little interface and rendering + */ +class MyGlutWin: public Utils::SimpleGlutWin +{ +public: + + void myRedraw(); + + PFP::REAL gWidthObj; + PFP::VEC3 gPosObj; + + Algo::Render::VBO::MapRender_VBO* m_render; + + Utils::GLSLShader shaders[4]; + + Geom::Vec4f colSpec; + float shininess; + + int rt; + + MyGlutWin(int* argc, char **argv, int winX, int winY) : SimpleGlutWin(argc, argv, winX, winY),rt(0) + { + shaders[0].loadShaders("phong_gl2.vert","phong_gl2.frag"); + + colSpec = Geom::Vec4f(0.9f, 0.9f, 0.9f, 1.0f) ; + shininess = 80.0f ; + } + ~MyGlutWin() + { + delete m_render ; + } +}; + + + + +void MyGlutWin::myRedraw() +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glPushMatrix(); + + // center the scene + float sc = 50./gWidthObj; + glScalef(sc,sc,sc); + glTranslatef(-gPosObj[0],-gPosObj[1],-gPosObj[2]); + + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + glEnable(GL_LIGHTING); + glEnable(GL_COLOR_MATERIAL); + + // some materials + glMaterialfv(GL_FRONT, GL_SPECULAR, colSpec.data()) ; + glMaterialf(GL_FRONT, GL_SHININESS, shininess) ; + + // bin shader + shaders[0].bind(); + + // draw triangles + m_render->draw(Algo::Render::VBO::TRIANGLES) ; + + // unbind (in case of other rendering wihtout shader) + shaders[0].unbind(); + + glPopMatrix(); + + +} + + + + +int main(int argc, char **argv) +{ + + // instanciation of the interface + MyGlutWin mgw(&argc, argv, 800, 800); + + // declaration of the map + PFP::MAP myMap; + + AttributeHandler position = myMap.addAttribute(VERTEX_ORBIT, "position"); + AttributeHandler normal = myMap.addAttribute(VERTEX_ORBIT, "normal"); + + Algo::Modelisation::Polyhedron prim3(myMap, position); + prim3.tore_topo(16, 32); + prim3.embedTore(30.0f,10.0f); + + // compute the normal of mesh + Algo::Geometry::computeNormalVertices(myMap,position,normal); + + mgw.init(); + + glClearColor(0.1,0.1,0.1,0.0); + glEnable(GL_DEPTH_TEST); + + // computation of the bounding box + Geom::BoundingBox bb = Algo::Geometry::computeBoundingBox(myMap, position); + mgw.gWidthObj = std::max(std::max(bb.size(0), bb.size(1)), bb.size(2)); + mgw.gPosObj = (bb.min() + bb.max()) / PFP::REAL(2); + + + // instanciation of the vbo renderer + mgw.m_render = new Algo::Render::VBO::MapRender_VBO(); + + // vertex attribute declaration (max 12) + mgw.m_render->useVertexAttributeName("ColorPerVertex",mgw.shaders[0]); + + // must relink the shader after binding attributes + mgw.shaders[0].link(); + + // copy data from map attributes to vbo for vertex attribute + mgw.m_render->updateVAData("ColorPerVertex", normal); + + // copy data from map attributes to vbo + mgw.m_render->updateData(Algo::Render::VBO::POSITIONS, position); + mgw.m_render->updateData(Algo::Render::VBO::NORMALS, normal); + + // update the renderer (primitives) + SelectorTrue allDarts; + mgw.m_render->initPrimitives(myMap, allDarts,Algo::Render::VBO::TRIANGLES); +// mgw.m_render->initPrimitives(myMap, allDarts,Algo::Render::VBO::LINES); +// mgw.m_render->initPrimitives(myMap, allDarts,Algo::Render::VBO::POINTS); + + + + mgw.mainLoop(); + + return 0; +} diff --git a/include/Algo/Render/vbo_MapRender.h b/include/Algo/Render/vbo_MapRender.h index 3835c04a3dc58e248bf33f0d8d47bb7b963b7736..9298c725f07339753b7f86e19a7836409c4b37ff 100644 --- a/include/Algo/Render/vbo_MapRender.h +++ b/include/Algo/Render/vbo_MapRender.h @@ -35,6 +35,8 @@ #include "Container/convert.h" #include "Geometry/vector_gen.h" +#include "Utils/GLSLShader.h" + namespace CGoGN { @@ -71,13 +73,26 @@ enum bufferIndex { FLAT_BUFFER = 3, POSITIONS_BUFFER = 4, NORMALS_BUFFER = 5, - COLORS_BUFFER = 6 - - + COLORS_BUFFER = 6, + FIRST_ATTRIBUTE_BUFFER = 7 } ; -const unsigned int NB_BUFFERS = 7 ; +const unsigned int NB_BUFFERS = 20 ; +// Warning using attributes forbid using the following buildin attributes +// gl_SecondaryColor +// gl_FogCoord +// gl_MultiTexCoord0 +// gl_MultiTexCoord1 +// gl_MultiTexCoord2 +// gl_MultiTexCoord3 +// gl_MultiTexCoord4 +// gl_MultiTexCoord5 +// gl_MultiTexCoord6 +// gl_MultiTexCoord7 +const unsigned int FIRST_VERTEX_ATTRIB = 4 ; + +const unsigned int NB_ATTRIBUTES = 12 ; class MapRender_VBO { @@ -90,6 +105,15 @@ protected: bool m_allocatedBuffers[NB_BUFFERS] ; bool m_usedBuffers[NB_BUFFERS] ; + bool m_allocatedAttributes[NB_ATTRIBUTES] ; + bool m_usedAttributes[NB_ATTRIBUTES] ; + unsigned int m_AttributesDataSize[NB_ATTRIBUTES]; + + unsigned int m_nbVertexAttrib; + + std::map m_attributebyName; + + /** * number of indices of triangles */ @@ -136,7 +160,59 @@ public: void enableBuffers(int buffersMask) ; void disableBuffers(int buffersMask) ; + + /** + * update the data for vertex attributes + * @param vertex_attrib vertex attrib id + * @param attrib attribute where data is stored + * @param conv Callback of attribute conversion (NULL if direct copy, default value) + */ + template + void updateVAData(unsigned int vertex_attrib, const ATTR_HANDLER& attrib, ConvertAttrib* conv = NULL) ; + + /** + * update the data for vertex attributes + * @param va_name vertex attrib name (in shader) + * @param attrib attribute where data is stored + * @param conv Callback of attribute conversion (NULL if direct copy, default value) + */ + template + void updateVAData(const std::string& name, const ATTR_HANDLER& attrib, ConvertAttrib* conv = NULL) ; + + + /** + * enable a vertex attribute for rendering (updateDate automatically enable attrib) + */ + void enableVertexAttrib(const std::string& name); + + /** + * disable a vertex attribute for rendering + */ + void disableVertexAttrib(const std::string& name); + + + /** + * associate a name to a vertex attribute + * @param name the name in shader + * @param sh the shader + * @return the id to use with update (if not using name) + */ + unsigned int useVertexAttributeName(const std::string& name, const Utils::GLSLShader& sh); + protected: + + unsigned int vbo_index_attribute( unsigned int att) { return att + FIRST_ATTRIBUTE_BUFFER - FIRST_VERTEX_ATTRIB;} + + /** + * enable a vertex attribute for rendering (updateDate automatically enable attrib) + */ + void enableVertexAttrib(unsigned int index); + + /** + * disable a vertex attribute for rendering + */ + void disableVertexAttrib(unsigned int index); + /** * fill buffer directly from attribute */ diff --git a/include/Algo/Render/vbo_MapRender.hpp b/include/Algo/Render/vbo_MapRender.hpp index dff8b2ca1491ffc1ff7d3566dade312983c2182f..b81557db3974612924c8cafbbfeddcd123924c51 100644 --- a/include/Algo/Render/vbo_MapRender.hpp +++ b/include/Algo/Render/vbo_MapRender.hpp @@ -37,6 +37,111 @@ namespace VBO { +// inline functions: +inline void MapRender_VBO::enableVertexAttrib(unsigned int index) +{ + m_usedAttributes[index] = true ; +} + +inline void MapRender_VBO::disableVertexAttrib(unsigned int index) +{ + m_usedAttributes[index] = false ; +} + + +/** + * enable a vertex attribute for rendering (updateDate automatically enable attrib) + */ +inline void MapRender_VBO::enableVertexAttrib(const std::string& name) +{ + std::map::iterator it = m_attributebyName.find(name); + if (it != m_attributebyName.end()) + enableVertexAttrib(it->second); + else + std::cerr <<"enableVertexAttrib: unknown attribute "<< name << std::endl; +} + + + +inline void MapRender_VBO::disableVertexAttrib(const std::string& name) +{ + std::map::iterator it = m_attributebyName.find(name); + if (it != m_attributebyName.end()) + disableVertexAttrib(it->second); + else + std::cerr <<"disableVertexAttrib: unknown attribute "<< name << std::endl; +} + + + +inline unsigned int MapRender_VBO::useVertexAttributeName(const std::string& name, const Utils::GLSLShader& sh) +{ + unsigned int vertex_attrib =0; + + std::map::iterator it = m_attributebyName.find(name); + if (it == m_attributebyName.end()) + { + vertex_attrib = m_nbVertexAttrib++; + m_attributebyName.insert(std::pair(name,vertex_attrib)); + } + else + vertex_attrib = it->second; + + sh.bindAttrib(vertex_attrib+FIRST_VERTEX_ATTRIB,name.c_str()); + + return vertex_attrib; +} + + +template +void MapRender_VBO::updateVAData(unsigned int vertex_attrib, const ATTR_HANDLER& attrib, ConvertAttrib* conv) +{ + // choisit le bon buffer en fonction du paramètre upType + + unsigned int indexVBO = vertex_attrib + FIRST_ATTRIBUTE_BUFFER; + + if (! m_allocatedAttributes[vertex_attrib] ) + { + glGenBuffersARB(1, &(m_VBOBuffers[indexVBO])) ; + m_allocatedAttributes[vertex_attrib] = true ; + } + + + m_usedAttributes[vertex_attrib] = true ; + m_AttributesDataSize[vertex_attrib]= sizeof(typename ATTR_HANDLER::DATA_TYPE) / sizeof(float); + + + if (conv) + fillBufferConvert(indexVBO, attrib, conv) ; + else + fillBufferDirect(indexVBO, attrib) ; +} + + + + + + +template +void MapRender_VBO::updateVAData(const std::string& name, const ATTR_HANDLER& attrib, ConvertAttrib* conv) +{ + unsigned int vertex_attrib = 0; + + std::map::iterator it = m_attributebyName.find(name); + if (it == m_attributebyName.end()) + { + vertex_attrib = m_nbVertexAttrib++; + m_attributebyName.insert(std::pair(name,vertex_attrib)); + std::cerr << "warning update data with unknown name, adding vertex attribute"<< std::endl; + } + else + { + vertex_attrib = it->second; + } + + updateVAData(vertex_attrib,attrib,conv); +} + template void MapRender_VBO::updateData(int upType, const ATTR_HANDLER& attrib, ConvertAttrib* conv) @@ -323,14 +428,6 @@ void MapRender_VBO::initPrimitives(typename PFP::MAP& map, const FunctorSelect& initLines(map,good,tableIndices,thread) ; m_nbIndicesLines = tableIndices.size(); vbo_ind = m_VBOBuffers[LINE_INDICES]; - - for (unsigned int i=0; i< tableIndices.size(); ++i) - { - std::cout << tableIndices[i]<< "/"; - if (i%2 == 1) std::cout << std::endl; - } - std::cout << std::endl; - break; case POINTS: initPoints(map,good,tableIndices,thread); diff --git a/include/Utils/GLSLShader.h b/include/Utils/GLSLShader.h index a7a0b2b3647df4c4c939b8466ff54d4e7bc4420b..f3f8943a6bdba6d8050e2763a3d980a4d93f00cc 100644 --- a/include/Utils/GLSLShader.h +++ b/include/Utils/GLSLShader.h @@ -196,6 +196,11 @@ public: bool loadShaders(const std::string& vs, const std::string& fs, const std::string& gs, GLint inputGeometryPrimitive=GL_TRIANGLES,GLint outputGeometryPrimitive=GL_TRIANGLES); + /** + * Link the shader do it just after binding the attributes + */ + bool link(); + inline bool isCreated(); bool isBinded(); diff --git a/lib/Shaders/phong_gl2.frag b/lib/Shaders/phong_gl2.frag new file mode 100644 index 0000000000000000000000000000000000000000..33e829aecb34deafa13b816b45e0defe6e6222eb --- /dev/null +++ b/lib/Shaders/phong_gl2.frag @@ -0,0 +1,29 @@ +//Pixel_Shader + +varying vec3 normal, lightDir, eyeVec; +varying vec3 vcolor; + +void main (void) +{ + vec4 final_color = vec4(0.0,0.0,0.0,0.0); + + vec3 N = normalize(normal); + vec3 L = normalize(lightDir); + + float lambertTerm = dot(N,L); + + if(lambertTerm > 0.0) + { + final_color += vec4(vcolor,1.0) * lambertTerm; + + vec3 E = normalize(eyeVec); + vec3 R = reflect(-L, N); + float specular = pow( max(dot(R, E), 0.0), + gl_FrontMaterial.shininess ); + final_color += gl_FrontMaterial.specular * + specular; + } + + gl_FragColor = final_color; + +} diff --git a/lib/Shaders/phong_gl2.vert b/lib/Shaders/phong_gl2.vert new file mode 100644 index 0000000000000000000000000000000000000000..c93d8b2bbaf1065193f0cfc41cf9e6a0d9e2e682 --- /dev/null +++ b/lib/Shaders/phong_gl2.vert @@ -0,0 +1,20 @@ +//Vertex_Shader + +attribute vec3 ColorPerVertex; + +varying vec3 normal, lightDir, eyeVec; +varying vec3 vcolor; + +void main() +{ + normal = gl_NormalMatrix * gl_Normal; + + vec3 vVertex = vec3(gl_ModelViewMatrix * gl_Vertex); + + lightDir = vec3(gl_LightSource[0].position.xyz - vVertex); + eyeVec = -vVertex; + + vcolor = ColorPerVertex; + + gl_Position = ftransform(); +} diff --git a/src/Algo/Render/vbo_MapRender.cpp b/src/Algo/Render/vbo_MapRender.cpp index dd7d343948405fc5d9d13fa0a09ff2caa075fb84..ec10cdbaf6423121deaa0eb79256d5d9b25c0f3b 100644 --- a/src/Algo/Render/vbo_MapRender.cpp +++ b/src/Algo/Render/vbo_MapRender.cpp @@ -37,6 +37,7 @@ namespace VBO { MapRender_VBO::MapRender_VBO(): + m_nbVertexAttrib(0), m_nbIndicesTri(0), m_nbIndicesLines(0) { @@ -46,6 +47,14 @@ MapRender_VBO::MapRender_VBO(): m_allocatedBuffers[i] = false ; m_usedBuffers[i] = false ; } + + for(unsigned int i = 0; i < NB_ATTRIBUTES; ++i) + { + m_allocatedAttributes[i] = false ; + m_usedAttributes[i] = false ; + m_AttributesDataSize[i]=0; + } + } MapRender_VBO::~MapRender_VBO() @@ -56,6 +65,7 @@ MapRender_VBO::~MapRender_VBO() MapRender_VBO::MapRender_VBO(const MapRender_VBO& mrvbo): + m_nbVertexAttrib(mrvbo.m_nbVertexAttrib), m_nbIndicesTri(0), m_nbIndicesLines(0) { @@ -73,6 +83,16 @@ MapRender_VBO::MapRender_VBO(const MapRender_VBO& mrvbo): m_allocatedBuffers[i] = mrvbo.m_allocatedBuffers[i] ; m_usedBuffers[i] = mrvbo.m_usedBuffers[i] ; } + + for(unsigned int i = 0; i < NB_ATTRIBUTES; ++i) + { + m_allocatedAttributes[i] = mrvbo.m_allocatedAttributes[i] ; + m_usedAttributes[i] = mrvbo.m_usedAttributes[i] ; + m_AttributesDataSize[i] = mrvbo.m_AttributesDataSize[i]; + } + + + } @@ -163,6 +183,15 @@ void MapRender_VBO::drawTriangles(bool bindColors) } } + for(unsigned int j = 0; j < m_nbVertexAttrib; ++j) + if(m_usedAttributes[j]) + { + glBindBufferARB(GL_ARRAY_BUFFER, m_VBOBuffers[j+ FIRST_ATTRIBUTE_BUFFER]); + glEnableVertexAttribArray(j+FIRST_VERTEX_ATTRIB); + glVertexAttribPointer(j+FIRST_VERTEX_ATTRIB, m_AttributesDataSize[j], GL_FLOAT, false, 0, 0); + } + + glDrawElements(GL_TRIANGLES, m_nbIndicesTri, GL_UNSIGNED_INT, 0); glDisableClientState(GL_INDEX_ARRAY); @@ -186,6 +215,12 @@ void MapRender_VBO::drawTriangles(bool bindColors) } } } + + + for(unsigned int j = 0; j < m_nbVertexAttrib; ++j) + if(m_usedAttributes[j]) + glDisableVertexAttribArray(j+FIRST_VERTEX_ATTRIB); + } void MapRender_VBO::drawLines(bool bindColors) @@ -218,6 +253,14 @@ void MapRender_VBO::drawLines(bool bindColors) } } + for(unsigned int j = 0; j < m_nbVertexAttrib; ++j) + if(m_usedAttributes[j]) + { + glBindBufferARB(GL_ARRAY_BUFFER, m_VBOBuffers[j+ FIRST_ATTRIBUTE_BUFFER]); + glEnableVertexAttribArray(j+FIRST_VERTEX_ATTRIB); + glVertexAttribPointer(j+FIRST_VERTEX_ATTRIB, m_AttributesDataSize[j], GL_FLOAT, false, 0, 0); + } + glDrawElements(GL_LINES, m_nbIndicesLines, GL_UNSIGNED_INT, 0); glDisableClientState(GL_INDEX_ARRAY); @@ -240,6 +283,11 @@ void MapRender_VBO::drawLines(bool bindColors) } } } + + for(unsigned int j = 0; j < m_nbVertexAttrib; ++j) + if(m_usedAttributes[j]) + glDisableVertexAttribArray(j+FIRST_VERTEX_ATTRIB); + } void MapRender_VBO::drawPoints(bool bindColors) @@ -272,6 +320,14 @@ void MapRender_VBO::drawPoints(bool bindColors) } } + for(unsigned int j = 0; j < m_nbVertexAttrib; ++j) + if(m_usedAttributes[j]) + { + glBindBufferARB(GL_ARRAY_BUFFER, m_VBOBuffers[j+ FIRST_ATTRIBUTE_BUFFER]); + glEnableVertexAttribArray(j+FIRST_VERTEX_ATTRIB); + glVertexAttribPointer(j+FIRST_VERTEX_ATTRIB, m_AttributesDataSize[j], GL_FLOAT, false, 0, 0); + } + glDrawElements(GL_POINTS, m_nbIndicesPoints, GL_UNSIGNED_INT, 0) ; glDisableClientState(GL_INDEX_ARRAY); @@ -296,6 +352,11 @@ void MapRender_VBO::drawPoints(bool bindColors) } } } + + for(unsigned int j = 0; j < m_nbVertexAttrib; ++j) + if(m_usedAttributes[j]) + glDisableVertexAttribArray(j+FIRST_VERTEX_ATTRIB); + } diff --git a/src/Utils/GLSLShader.cpp b/src/Utils/GLSLShader.cpp index c9c9160e11ed8158d37f94c78b68d279576e8726..219caf8bb3fd1747f593a7bef30a036a3134cf56 100644 --- a/src/Utils/GLSLShader.cpp +++ b/src/Utils/GLSLShader.cpp @@ -428,6 +428,39 @@ bool GLSLShader::create(GLint inputGeometryPrimitive,GLint outputGeometryPrimiti } +bool GLSLShader::link() +{ + int status; + char *info_log; + + + /*** link program object ***/ + glLinkProgramARB( m_program_object ); + + glGetObjectParameterivARB( m_program_object, GL_OBJECT_LINK_STATUS_ARB, &status ); + if( !status ) + { + std::cerr << "ERROR - GLSLShader::create() - error occured while linking shader program." << std::endl; + info_log = getInfoLog( m_program_object ); + std::cerr << " LINK " << info_log << std::endl; + delete [] info_log; + + glDetachObjectARB( m_program_object, m_vertex_shader_object ); + glDetachObjectARB( m_program_object, m_fragment_shader_object ); + if (m_geom_shader_object) + glDetachObjectARB( m_program_object, m_geom_shader_object ); + glDeleteObjectARB( m_program_object ); + m_program_object = 0; + + return false; + } + + return true; +} + + + + bool GLSLShader::bind() { if( m_program_object ) diff --git a/src/Utils/glutwin_gl3.cpp b/src/Utils/glutwin_gl3.cpp index 1058f7c0afd9257c1742276a3f175a88ebb29606..11cbc89590da391b2df879b48f338d05b59a2a03 100644 --- a/src/Utils/glutwin_gl3.cpp +++ b/src/Utils/glutwin_gl3.cpp @@ -125,6 +125,10 @@ SimpleGlutWinGL3::SimpleGlutWinGL3(int* argc, char **argv, int winX, int winY) std::cout << "OpenGL v"<