Commit be1ee120 authored by Sylvain Thery's avatar Sylvain Thery

Ajout rendu et interface OpenGL3

parent ea955ff5
......@@ -16,6 +16,7 @@ include_directories(
${CGoGN_ROOT_DIR}/ThirdParty/gzstream
${CGoGN_ROOT_DIR}/ThirdParty/OpenCTM
${CGoGN_ROOT_DIR}/ThirdParty/Assimp/include
${CGoGN_ROOT_DIR}/ThirdParty/glm
${CGoGN_ROOT_DIR}/include
)
......@@ -56,3 +57,9 @@ add_executable( tuto_mt tuto_mt.cpp)
target_link_libraries( tuto_mt
containerD topologyD utilsD algoD ${COMMON_LIBS} boost_thread)
# container topology utils algo ${COMMON_LIBS} boost_thread)
add_executable( tuto_ogl3 tuto_ogl3.cpp)
target_link_libraries( tuto_ogl3
containerD topologyD utilsD algoD ${COMMON_LIBS} )
# container topology utils algo ${COMMON_LIBS} )
/*******************************************************************************
* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps *
* version 0.1 *
* Copyright (C) 2009, IGG Team, LSIIT, University of Strasbourg *
* *
* This library is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation; either version 2.1 of the License, or (at your *
* option) any later version. *
* *
* This library is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
* for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this library; if not, write to the Free Software Foundation, *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
* *
* Web site: https://iggservis.u-strasbg.fr/CGoGN/ *
* Contact information: cgogn@unistra.fr *
* *
*******************************************************************************/
#ifndef _GL3_MAP_RENDER_
#define _GL3_MAP_RENDER_
#include <GL/glew.h>
#include <vector>
#include <list>
#include "Topology/generic/dart.h"
#include "Topology/generic/functor.h"
#include "Topology/generic/attributeHandler.h"
#include "Container/convert.h"
#include "Geometry/vector_gen.h"
namespace CGoGN
{
namespace Algo
{
namespace Render
{
namespace GL3
{
enum drawingType {
TRIANGLES = 1,
LINES = 2,
POINTS = 4,
EXPLODED = 8,
FLAT_TRIANGLES = 16,
ERR = 32
} ;
enum bufferIndex {
TRIANGLE_INDICES = 0,
LINE_INDICES = 1,
POINT_INDICES = 2,
FLAT_BUFFER = 3,
FIRST_ATTRIBUTE_BUFFER = 4,
} ;
const unsigned int NB_BUFFERS = 16 ;
class MapRender
{
protected:
/**
* vbo buffers
*/
GLuint m_VBOBuffers[NB_BUFFERS] ;
// bool m_allocatedBuffers[NB_BUFFERS] ;
// bool m_usedBuffers[NB_BUFFERS] ;
bool m_allocatedAttributes[NB_BUFFERS] ;
bool m_usedAttributes[NB_BUFFERS] ;
unsigned int m_AttributesDataSize[NB_BUFFERS];
/**
* number of indices of triangles
*/
GLuint m_nbIndicesTri ;
/**
* number of indices of lines
*/
GLuint m_nbIndicesLines ;
/**
* number of indices of points
*/
GLuint m_nbIndicesPoints ;
/**
* number of elts for flat vbo
*/
GLuint m_nbFlatElts;
public:
/**
* Constructor
*/
MapRender() ;
/**
* Constructor that share vertices attributes vbo (position/normals/colors...)
*/
MapRender(const MapRender& mrvbo);
/**
* Destructor
*/
~MapRender() ;
/**
* update the data
* @param uptype that have to be updated: POSITIONS, NORMALS, COLORS, TEXCOORDS, ???
* @param attribId attribute where data is stored
* @param conv Callback of attribute conversion (NULL if direct copy, default value)
*/
template <typename ATTR_HANDLER>
void updateData(unsigned int vertex_attrib, const ATTR_HANDLER& attrib, ConvertAttrib* conv = NULL) ;
/**
* 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);
protected:
/**
* fill buffer directly from attribute
*/
template <typename ATTR_HANDLER>
void fillBufferDirect(unsigned int indexVBO, const ATTR_HANDLER& attrib) ;
/**
* fill buffer with conversion from attribute
*/
template <typename ATTR_HANDLER>
void fillBufferConvert(unsigned int indexVBO, const ATTR_HANDLER& attrib, ConvertAttrib* conv) ;
/**
* addition of indices table of one triangle
* @param d a dart of the triangle
* @param tableIndices the indices table
*/
template <typename PFP>
void addTri(typename PFP::MAP& map, Dart d, std::vector<GLuint>& tableIndices) ;
public:
/**
* creation of indices table of triangles (optimized order)
* @param tableIndices the table where indices are stored
*/
template <typename PFP>
void initTriangles(typename PFP::MAP& map, const FunctorSelect& good,std::vector<GLuint>& tableIndices, unsigned int thread=0) ;
template <typename PFP>
void initTrianglesOptimized(typename PFP::MAP& map, const FunctorSelect& good,std::vector<GLuint>& tableIndices, unsigned int thread=0) ;
/**
* creation of indices table of lines (optimized order)
* @param tableIndices the table where indices are stored
*/
template <typename PFP>
void initLines(typename PFP::MAP& map, const FunctorSelect& good,std::vector<GLuint>& tableIndices, unsigned int thread=0) ;
template <typename PFP>
void initLinesOptimized(typename PFP::MAP& map, const FunctorSelect& good,std::vector<GLuint>& tableIndices, unsigned int thread=0) ;
/**
* creation of indices table of points
* @param tableIndices the table where indices are stored
*/
template <typename PFP>
void initPoints(typename PFP::MAP& map, const FunctorSelect& good,std::vector<GLuint>& tableIndices, unsigned int thread=0) ;
/**
* creation of VBO for flat faces rendering
*/
template <typename PFP>
void initFlatTriangles(typename PFP::MAP& map, unsigned int vertex_attrib_position, const FunctorSelect& good=SelectorTrue() , unsigned int thread=0);
/**
* initialization of the VBO indices primitives
* computed by a traversal of the map
* @param prim primitive to draw: VBO_TRIANGLES, VBO_LINES
*/
template <typename PFP>
void initPrimitives(typename PFP::MAP& map, const FunctorSelect& good, int prim, bool optimized = true, unsigned int thread=0) ;
/**
* initialization of the VBO indices primitives
* using the given table
* @param prim primitive to draw: VBO_TRIANGLES, VBO_LINES
*/
void initPrimitives(int prim, std::vector<GLuint>& tableIndices) ;
protected:
/**
* Drawing triangles function
*/
void drawTriangles(bool bindColors = true) ;
/**
* Drawing lines function
*/
void drawLines(bool bindColors = true) ;
/**
* Drawing points function
*/
void drawPoints(bool bindColors = true) ;
/**
* Drawing flat faces function
*/
void drawFlat();
public:
/**
* draw the VBO (function to call in the drawing callback)
*/
void draw(int prim, bool bindColors = true) ;
} ;
} // namespace VBO
} // namespace Render
} // namespace Algo
} // namespace CGoGN
#include "Algo/Render/gl3mapRender.hpp"
#endif
/*******************************************************************************
* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps *
* version 0.1 *
* Copyright (C) 2009, IGG Team, LSIIT, University of Strasbourg *
* *
* This library is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation; either version 2.1 of the License, or (at your *
* option) any later version. *
* *
* This library is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
* for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this library; if not, write to the Free Software Foundation, *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
* *
* Web site: https://iggservis.u-strasbg.fr/CGoGN/ *
* Contact information: cgogn@unistra.fr *
* *
*******************************************************************************/
#include "Topology/generic/dartmarker.h"
#include "Topology/generic/cellmarker.h"
namespace CGoGN
{
namespace Algo
{
namespace Render
{
namespace GL3
{
template <typename ATTR_HANDLER>
void MapRender::updateData(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 <typename ATTR_HANDLER>
void MapRender::fillBufferDirect(unsigned int indexVBO, const ATTR_HANDLER& attrib)
{
AttribMultiVect<typename ATTR_HANDLER::DATA_TYPE>* mv = attrib.getDataVector() ;
std::vector<void*> addr;
unsigned int byteTableSize;
unsigned int nbb = mv->getStartAddresses(addr, byteTableSize);
glBindBufferARB(GL_ARRAY_BUFFER, m_VBOBuffers[indexVBO]);
glBufferDataARB(GL_ARRAY_BUFFER, nbb * byteTableSize, 0, GL_STREAM_DRAW);
unsigned int offset = 0;
for (unsigned int i = 0; i < nbb; ++i)
{
glBufferSubDataARB(GL_ARRAY_BUFFER, offset, byteTableSize, addr[i]);
offset += byteTableSize;
}
}
template <typename ATTR_HANDLER>
void MapRender::fillBufferConvert(unsigned int indexVBO, const ATTR_HANDLER& attrib, ConvertAttrib* conv)
{
AttribMultiVect<typename ATTR_HANDLER::DATA_TYPE>* mv = attrib.getDataVector() ;
std::vector<void*> addr;
unsigned int byteTableSize;
unsigned int nbb = mv->getStartAddresses(addr, byteTableSize);
// alloue la memoire pour le buffer et initialise le conv
conv->reserve(mv->BlockSize());
// bind buffer to update
glBindBufferARB(GL_ARRAY_BUFFER, m_VBOBuffers[indexVBO]);
glBufferDataARB(GL_ARRAY_BUFFER, nbb * conv->sizeBuffer(), 0, GL_STREAM_DRAW);
unsigned int offset = 0;
for (unsigned int i = 0; i < nbb; ++i)
{
// convertit les donnees dans le buffer de conv
conv->convert(addr[i]);
// update sub-vbo
glBufferSubDataARB(GL_ARRAY_BUFFER, offset, conv->sizeBuffer(), conv->buffer());
// block suivant
offset += conv->sizeBuffer();
}
// libere la memoire de la conversion
conv->release();
}
template<typename PFP>
inline void MapRender::addTri(typename PFP::MAP& map, Dart d, std::vector<GLuint>& tableIndices)
{
Dart a = d;
Dart b = map.phi1(a);
Dart c = map.phi1(b);
// loop to cut a polygon in triangle on the fly (works only with convex faces)
do
{
tableIndices.push_back(map.getEmbedding(d, VERTEX_ORBIT));
tableIndices.push_back(map.getEmbedding(b, VERTEX_ORBIT));
tableIndices.push_back(map.getEmbedding(c, VERTEX_ORBIT));
b = c;
c = map.phi1(b);
} while (c != d);
}
template<typename PFP>
void MapRender::initTriangles(typename PFP::MAP& map, const FunctorSelect& good, std::vector<GLuint>& tableIndices, unsigned int thread)
{
DartMarker m(map,thread);
tableIndices.reserve(4*map.getNbDarts()/3);
for(Dart dd = map.begin(); dd != map.end(); map.next(dd))
{
if(!m.isMarked(dd) && good(dd))
{
addTri<PFP>(map, dd, tableIndices);
m.markOrbit(FACE_ORBIT, dd);
}
}
}
template<typename PFP>
void MapRender::initTrianglesOptimized(typename PFP::MAP& map, const FunctorSelect& good, std::vector<GLuint>& tableIndices, unsigned int thread)
{
#define LIST_SIZE 20
DartMarker m(map,thread);
// reserve memory for triangles ( nb indices == nb darts )
// and a little bit more
// if lots of polygonal faces, realloc is done by vector
tableIndices.reserve(4*map.getNbDarts()/3);
for (Dart dd = map.begin(); dd != map.end(); map.next(dd))
{
if (!m.isMarked(dd))
{
std::list<Dart> bound;
if(good(dd))
addTri<PFP>(map,dd,tableIndices);
m.markOrbit(FACE_ORBIT, dd);
bound.push_back(dd);
int nb = 1;
do
{
Dart e = bound.back();
Dart ee = e;
do
{
Dart f = ee;
do
{
if (!m.isMarked(f))
{
if(good(f))
addTri<PFP>(map, f, tableIndices);
m.markOrbit(FACE_ORBIT, f);
bound.push_back(map.phi1(f));
++nb;
if (nb > LIST_SIZE)
{
bound.pop_front();
--nb;
}
}
f = map.phi1(map.phi2(f));
} while (f != ee);
ee = map.phi1(ee);
} while (ee != e);
bound.pop_back();
--nb;
} while (!bound.empty());
}
}
#undef LIST_SIZE
}
template<typename PFP>
void MapRender::initLines(typename PFP::MAP& map, const FunctorSelect& good, std::vector<GLuint>& tableIndices, unsigned int thread)
{
DartMarker m(map,thread);
tableIndices.reserve(map.getNbDarts());
for(Dart d = map.begin(); d != map.end(); map.next(d))
{
if(!m.isMarked(d) && good(d))
{
tableIndices.push_back(map.getEmbedding(d, VERTEX_ORBIT));
tableIndices.push_back(map.getEmbedding(map.phi2(d), VERTEX_ORBIT));
m.markOrbit(EDGE_ORBIT, d);
}
}
}
template<typename PFP>
void MapRender::initLinesOptimized(typename PFP::MAP& map, const FunctorSelect& good, std::vector<GLuint>& tableIndices, unsigned int thread)
{
#define LIST_SIZE 20
DartMarker m(map,thread);
// reserve memory for edges indices ( nb indices == nb darts)
tableIndices.reserve(map.getNbDarts());
for (Dart dd = map.begin(); dd != map.end(); map.next(dd))
{
if (!m.isMarked(dd))
{
std::list<Dart> bound;
bound.push_back(dd);
int nb = 1;
do
{
Dart e = bound.back();
Dart ee = e;
do
{
Dart f = map.phi2(ee);
if (!m.isMarked(ee))
{
if(good(ee))
tableIndices.push_back(map.getEmbedding(ee, VERTEX_ORBIT));
if(good(f))
tableIndices.push_back(map.getEmbedding(map.phi1(ee), VERTEX_ORBIT));
m.markOrbit(EDGE_ORBIT, f);
bound.push_back(f);
++nb;
if (nb > LIST_SIZE)
{
bound.pop_front();
--nb;
}
}
ee = map.phi1(f);
} while (ee != e);
bound.pop_back();
--nb;
} while (!bound.empty());
}
}
#undef LIST_SIZE
}
template<typename PFP>
void MapRender::initPoints(typename PFP::MAP& map, const FunctorSelect& good, std::vector<GLuint>& tableIndices, unsigned int thread)
{
CellMarker m(map, VERTEX_ORBIT,thread) ;
tableIndices.reserve(map.getNbDarts()/5);
for(Dart d = map.begin(); d != map.end(); map.next(d))
{
if(!m.isMarked(d) && good(d))
{
tableIndices.push_back(map.getEmbedding(d, VERTEX_ORBIT));
m.mark(d) ;
}
}
}
template<typename PFP>
void MapRender::initPrimitives(typename PFP::MAP& map, const FunctorSelect& good, int prim, bool optimized, unsigned int thread)
{
std::vector<GLuint> tableIndices;
// indice du VBO a utiliser
int vbo_ind = 0;
switch(prim)
{
case FLAT_TRIANGLES:
break;
case TRIANGLES:
if(optimized)
initTrianglesOptimized<PFP>(map,good,tableIndices,thread);
else
initTriangles<PFP>(map,good,tableIndices,thread) ;
m_nbIndicesTri = tableIndices.size();
vbo_ind = m_VBOBuffers[TRIANGLE_INDICES];
break;
case LINES:
if(optimized)
initLinesOptimized<PFP>(map,good,tableIndices,thread);
else
initLines<PFP>(map,good,tableIndices,thread) ;
m_nbIndicesLines = tableIndices.size();
vbo_ind = m_VBOBuffers[LINE_INDICES];
break;
case POINTS:
initPoints<PFP>(map,good,tableIndices,thread);
m_nbIndicesPoints = tableIndices.size();
vbo_ind = m_VBOBuffers[POINT_INDICES];
break;
default:
std::cerr << "problem initializing VBO indices" << std::endl;
break;
}
unsigned int size = tableIndices.size();
// setup du buffer d'indices
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, vbo_ind);
glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER, size*sizeof(GLuint), &(tableIndices[0]), GL_STREAM_DRAW);
}
template<typename PFP>
void MapRender::initFlatTriangles( typename PFP::MAP& map, unsigned int vertex_attrib_position, const FunctorSelect& good, unsigned int thread)
{
std::vector<Geom::Vec3f> tableFlat;
tableFlat.reserve(3*map.getNbDarts()); // 3 in case of polygonal faces (less chance of realloc, but bigger allocation)
// map VBO of points for vertices positions
glBindBufferARB(GL_ARRAY_BUFFER, m_VBOBuffers[vertex_attrib_position+FIRST_ATTRIBUTE_BUFFER]);
Geom::Vec3f* tablePos = reinterpret_cast<Geom::Vec3f*>(glMapBuffer(GL_ARRAY_BUFFER,GL_READ_ONLY));
m_nbFlatElts=0;
// traversal of map for creating buffers
DartMarker m(map,thread);
for(Dart dd = map.begin(); dd != map.end(); map.next(dd))
{
if(!m.isMarked(dd) && good(dd))
{
Dart a = dd;
Dart b = map.phi1(a);
Dart c = map.phi1(b);
Geom::Vec3f& P = tablePos[map.getEmbedding(a, VERTEX_ORBIT)];