2015-06-04 02:18:35 +02:00
/****************************************************************************
* VCGLib o o *
* Visual and Computer Graphics Library o o *
* _ O _ *
* Copyright ( C ) 2004 \ / ) \ / *
* Visual Computing Lab / \ / | *
* ISTI - Italian National Research Council | *
* \ *
* All rights reserved . *
* *
* This program is free software ; you can redistribute it and / or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation ; either version 2 of the License , or *
* ( at your option ) any later version . *
* *
* This program 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 General Public License ( http : //www.gnu.org/licenses/gpl.txt) *
* for more details . *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# ifndef __VCG_GL_MESH_ATTRIBUTES_FEEDER
# define __VCG_GL_MESH_ATTRIBUTES_FEEDER
# include <queue>
# include <vector>
# include <map>
# include <algorithm>
# include <iostream>
2015-06-10 20:39:23 +02:00
# include <stdexcept>
2015-06-11 01:52:50 +02:00
# include <cstdio>
2015-06-04 02:18:35 +02:00
//#include <GL/glew.h>
# include <wrap/gl/space.h>
# include <wrap/gl/math.h>
# include <vcg/space/color4.h>
namespace vcg
{
2015-06-14 11:39:42 +02:00
//WARNING: All the classes derived from MemoryInfo has been intended to be instantiated as a singleton in the host application
2015-06-04 02:18:35 +02:00
//(i.e. in every application using it just an instance of a class derived from MemoryInfo should be declared).
class MemoryInfo
{
public :
class MemoryInfoException : public std : : exception
{
public :
MemoryInfoException ( const char * text )
: std : : exception ( ) , _exctext ( text ) { }
~ MemoryInfoException ( ) throw ( ) { }
inline const char * what ( ) const throw ( ) { return _exctext ; }
private :
const char * _exctext ;
} ;
MemoryInfo ( long long unsigned int originalmem )
: _originaltotalmemory ( originalmem ) , _currentfreememory ( _originaltotalmemory )
{
}
virtual ~ MemoryInfo ( ) { }
virtual void acquiredMemory ( long long unsigned int mem ) = 0 ;
virtual long long unsigned int usedMemory ( ) const = 0 ;
virtual long long unsigned int currentFreeMemory ( ) const = 0 ;
virtual void releasedMemory ( long long unsigned int mem = 0 ) = 0 ;
virtual bool isAdditionalMemoryAvailable ( long long unsigned int mem ) = 0 ;
protected :
const long long unsigned int _originaltotalmemory ;
long long unsigned int _currentfreememory ;
} ;
//WARNING: this is not a thread safe class. The object derived from MemoryInfo are intended to be used inside GLMeshAttributeFeeder as static variable in order to manage the available GPUMemory.
//We strongly recommend you to define in your code a thread safe version of the class, defining mutexed access member functions.
//This class should be consider just as a basic example for the implementations of the required functionalities.
//It is safe to use it just when the user has only one mesh to pass to the GPU.
class NotThreadSafeMemoryInfo : public MemoryInfo
{
public :
NotThreadSafeMemoryInfo ( long long unsigned int originalmem )
: MemoryInfo ( originalmem )
{
}
~ NotThreadSafeMemoryInfo ( ) { }
void acquiredMemory ( long long unsigned int mem )
{
if ( mem > _originaltotalmemory )
throw MemoryInfo : : MemoryInfoException ( " It has been requested more memory than the total one. \\ n " ) ;
else
if ( mem > _currentfreememory )
throw MemoryInfo : : MemoryInfoException ( " It has been requested more memory than the free available one. \\ n " ) ;
else
_currentfreememory - = mem ;
}
long long unsigned int usedMemory ( ) const
{
return _originaltotalmemory - _currentfreememory ;
}
long long unsigned int currentFreeMemory ( ) const
{
return _currentfreememory ;
}
void releasedMemory ( long long unsigned int mem = 0 )
{
if ( mem > _originaltotalmemory )
throw MemoryInfo : : MemoryInfoException ( " It has been released more memory than the total one. Something strange happened! \\ n " ) ;
else
_currentfreememory + = mem ;
}
bool isAdditionalMemoryAvailable ( long long unsigned int mem )
{
return ( _currentfreememory > = mem ) ;
}
} ;
struct GLFeedEnum
{
enum MESH_ATTRIBUTE_UPDATED
{
ATT_VERTPOSITION = 0x00000000 ,
ATT_VERTNORMAL = 0x00000001 ,
ATT_VERTCOLOR = 0x00000002 ,
ATT_VERTTEXTURE = 0x00000004 ,
ATT_FACENORMAL = 0x00000008 ,
ATT_FACECOLOR = 0x00000010 ,
ATT_WEDGETEXTURE = 0x00000020 ,
ATT_ALL = 0xffffffff
} ;
enum COLOR_MODALITY
{
CL_NONE = 0 ,
CL_PERVERT ,
CL_PERFACE ,
CL_PERMESH
} ;
enum NORMAL_MODALITY
{
NR_NONE = 0 ,
NR_PERVERT ,
NR_PERFACE
} ;
enum TEXTURE_MODALITY
{
TX_NONE = 0 ,
TX_PERVERT ,
TX_PERWEDGE
} ;
} ;
//WARNING! member functions of this class should be called by the host application using concurrency
template < typename MESHTYPE >
class GLMeshAttributesFeeder : public GLFeedEnum
{
public :
2015-06-10 20:13:28 +02:00
GLMeshAttributesFeeder ( /*const*/ MESHTYPE & mesh , MemoryInfo & meminfo , size_t perbatchtriangles )
2015-06-14 11:39:42 +02:00
: _mesh ( mesh ) , _gpumeminfo ( meminfo ) , _bo ( 8 , NULL ) /*,vaohandle(0)*/ , _lastfeedingusedreplicatedpipeline ( false ) , _perbatchsimplex ( perbatchtriangles ) , _chunkmap ( ) , _borendering ( false )
2015-06-04 02:18:35 +02:00
{
2015-06-14 11:39:42 +02:00
_bo [ VERTPOSITIONBO ] = new GLBufferObject ( 3 , GL_FLOAT , GL_ARRAY_BUFFER ) ;
_bo [ VERTNORMALBO ] = new GLBufferObject ( 3 , GL_FLOAT , GL_ARRAY_BUFFER ) ;
_bo [ FACENORMALBO ] = new GLBufferObject ( 3 , GL_FLOAT , GL_ARRAY_BUFFER ) ;
_bo [ VERTCOLORBO ] = new GLBufferObject ( 4 , GL_UNSIGNED_BYTE , GL_ARRAY_BUFFER ) ;
_bo [ FACECOLORBO ] = new GLBufferObject ( 4 , GL_UNSIGNED_BYTE , GL_ARRAY_BUFFER ) ;
_bo [ VERTTEXTUREBO ] = new GLBufferObject ( 2 , GL_FLOAT , GL_ARRAY_BUFFER ) ;
_bo [ WEDGETEXTUREBO ] = new GLBufferObject ( 2 , GL_FLOAT , GL_ARRAY_BUFFER ) ;
_bo [ VERTINDEXBO ] = new GLBufferObject ( 3 , GL_UNSIGNED_INT , GL_ELEMENT_ARRAY_BUFFER ) ;
2015-06-04 02:18:35 +02:00
}
~ GLMeshAttributesFeeder ( )
{
size_t ii = 0 ;
for ( typename std : : vector < GLBufferObject * > : : iterator it = _bo . begin ( ) ; it ! = _bo . end ( ) ; + + it )
{
if ( * it ! = NULL )
{
glDeleteBuffers ( 1 , & ( ( * it ) - > _bohandle ) ) ;
( * it ) - > _bohandle = 0 ;
}
delete _bo [ BO_NAMES ( ii ) ] ;
+ + ii ;
}
_bo . clear ( ) ;
2015-06-10 20:13:28 +02:00
//glDeleteVertexArrays(1,&vaohandle);
2015-06-04 02:18:35 +02:00
}
void setPerBatchTriangles ( size_t perbatchtriangles )
{
_perbatchsimplex = perbatchtriangles ;
}
size_t perBatchTriangles ( ) const
{
return _perbatchsimplex ;
}
bool renderedWithBO ( ) const
{
return _borendering ;
}
void update ( int mask )
{
if ( ( mask & ATT_VERTPOSITION ) | | ( mask & ATT_ALL ) )
_bo [ VERTPOSITIONBO ] - > _isvalid = false ;
if ( ( mask & ATT_VERTNORMAL ) | | ( mask & ATT_ALL ) )
_bo [ VERTNORMALBO ] - > _isvalid = false ;
if ( ( mask & ATT_FACENORMAL ) | | ( mask & ATT_ALL ) )
_bo [ FACENORMALBO ] - > _isvalid = false ;
if ( ( mask & ATT_VERTCOLOR ) | | ( mask & ATT_ALL ) )
_bo [ VERTCOLORBO ] - > _isvalid = false ;
if ( ( mask & ATT_FACECOLOR ) | | ( mask & ATT_ALL ) )
_bo [ FACECOLORBO ] - > _isvalid = false ;
if ( ( mask & ATT_VERTTEXTURE ) | | ( mask & ATT_ALL ) )
_bo [ VERTTEXTUREBO ] - > _isvalid = false ;
if ( ( mask & ATT_WEDGETEXTURE ) | | ( mask & ATT_ALL ) )
_bo [ WEDGETEXTUREBO ] - > _isvalid = false ;
if ( mask & ATT_ALL )
_bo [ VERTINDEXBO ] - > _isvalid = false ;
}
/*WARNING: the passTrianglesToOpenGL & the passPointsToOpenGL functions should be invoked with a reading mutex,
in order to be sure that the referenced mesh would not been changed when the mesh attributes are updated into the buffer objects .
textureindex contained the texture OpenGL ids loaded in the gpu memory by the main application */
2015-06-10 20:13:28 +02:00
void passTrianglesToOpenGL ( GLuint & vaohandlespecificperopenglcontext , NORMAL_MODALITY nm , COLOR_MODALITY cm , TEXTURE_MODALITY tm , const std : : vector < GLuint > & textureindex = std : : vector < GLuint > ( ) )
2015-06-04 02:18:35 +02:00
{
2015-06-14 11:39:42 +02:00
if ( tryToAllocatePerTriangleAttributesInBO ( vaohandlespecificperopenglcontext , nm , cm , tm ) )
2015-06-10 20:13:28 +02:00
drawTriangles ( vaohandlespecificperopenglcontext , nm , cm , tm , textureindex ) ;
2015-06-14 11:39:42 +02:00
else
immediateMode ( nm , cm , tm , textureindex ) ;
2015-06-04 02:18:35 +02:00
}
2015-06-10 20:13:28 +02:00
void passPointsToOpenGL ( GLuint & vaohandlespecificperopenglcontext , NORMAL_MODALITY nm , COLOR_MODALITY cm )
2015-06-04 02:18:35 +02:00
{
2015-06-14 11:39:42 +02:00
if ( tryToAllocatePerPointAttributesInBO ( vaohandlespecificperopenglcontext , nm , cm ) )
2015-06-10 20:13:28 +02:00
drawPoints ( vaohandlespecificperopenglcontext ) ;
2015-06-14 11:39:42 +02:00
else
immediateMode ( nm , cm , TX_NONE ) ;
2015-06-04 02:18:35 +02:00
}
2015-06-14 11:39:42 +02:00
enum BO_NAMES
{
VERTPOSITIONBO = 0 ,
VERTNORMALBO = 1 ,
FACENORMALBO = 2 ,
VERTCOLORBO = 3 ,
FACECOLORBO = 4 ,
VERTTEXTUREBO = 5 ,
WEDGETEXTUREBO = 6 ,
VERTINDEXBO = 7
} ;
protected :
2015-06-04 02:18:35 +02:00
struct GLBufferObject
{
2015-06-14 11:39:42 +02:00
GLBufferObject ( size_t components , GLenum gltype , GLenum target )
: _size ( 0 ) , _components ( components ) , _isvalid ( false ) , _gltype ( gltype ) , _target ( target ) , _bohandle ( 0 )
2015-06-04 02:18:35 +02:00
{
}
size_t getSizeOfGLType ( ) const
{
switch ( _gltype )
{
case ( GL_FLOAT ) :
return sizeof ( GLfloat ) ;
case ( GL_INT ) :
return sizeof ( GLint ) ;
case ( GL_UNSIGNED_INT ) :
return sizeof ( GLuint ) ;
case ( GL_UNSIGNED_BYTE ) :
return sizeof ( GLubyte ) ;
}
return 0 ;
}
size_t _size ;
const size_t _components ;
bool _isvalid ;
const GLenum _gltype ;
2015-06-14 11:39:42 +02:00
const GLenum _target ;
2015-06-04 02:18:35 +02:00
GLuint _bohandle ;
} ;
2015-06-14 11:39:42 +02:00
const GLBufferObject & getBufferObjectInfo ( BO_NAMES boname ) const
2015-06-04 02:18:35 +02:00
{
2015-06-14 11:39:42 +02:00
return _bo [ boname ] ;
}
2015-06-04 02:18:35 +02:00
long long unsigned int bufferObjectsMemoryRequired ( NORMAL_MODALITY nm , COLOR_MODALITY cm , TEXTURE_MODALITY tm , bool generateindex ) const
{
bool replicated = ( nm = = NR_PERFACE ) | | ( cm = = CL_PERFACE ) | | ( tm = = TX_PERWEDGE ) ;
long long unsigned int result ( 0 ) ;
result + = ( long long unsigned int ) boExpectedDimension ( VERTPOSITIONBO , replicated , generateindex ) ;
if ( nm = = NR_PERVERT )
result + = ( long long unsigned int ) boExpectedDimension ( VERTNORMALBO , replicated , generateindex ) ;
if ( nm = = NR_PERFACE )
result + = ( long long unsigned int ) boExpectedDimension ( FACENORMALBO , replicated , generateindex ) ;
if ( cm = = CL_PERVERT )
result + = ( long long unsigned int ) boExpectedDimension ( VERTCOLORBO , replicated , generateindex ) ;
if ( cm = = CL_PERFACE )
result + = ( long long unsigned int ) boExpectedDimension ( FACECOLORBO , replicated , generateindex ) ;
if ( tm = = TX_PERVERT )
result + = ( long long unsigned int ) boExpectedDimension ( VERTTEXTUREBO , replicated , generateindex ) ;
if ( tm = = TX_PERWEDGE )
result + = ( long long unsigned int ) boExpectedDimension ( WEDGETEXTUREBO , replicated , generateindex ) ;
result + = ( long long unsigned int ) boExpectedDimension ( VERTINDEXBO , replicated , generateindex ) ;
return result ;
}
2015-06-14 11:39:42 +02:00
void attributesToBeImportedInTriangleBasedPipeline ( std : : vector < bool > & importattribute , NORMAL_MODALITY nm , COLOR_MODALITY cm , TEXTURE_MODALITY tm ) const
2015-06-04 02:18:35 +02:00
{
importattribute [ VERTPOSITIONBO ] = true ;
importattribute [ VERTNORMALBO ] = vcg : : tri : : HasPerVertexNormal ( _mesh ) & & ( nm = = NR_PERVERT ) ;
importattribute [ FACENORMALBO ] = vcg : : tri : : HasPerFaceNormal ( _mesh ) & & ( nm = = NR_PERFACE ) ;
importattribute [ VERTCOLORBO ] = vcg : : tri : : HasPerVertexColor ( _mesh ) & & ( cm = = CL_PERVERT ) ;
importattribute [ FACECOLORBO ] = vcg : : tri : : HasPerFaceColor ( _mesh ) & & ( cm = = CL_PERFACE ) ;
importattribute [ VERTTEXTUREBO ] = vcg : : tri : : HasPerVertexTexCoord ( _mesh ) & & ( tm = = TX_PERVERT ) ;
importattribute [ WEDGETEXTUREBO ] = vcg : : tri : : HasPerWedgeTexCoord ( _mesh ) & & ( tm = = TX_PERWEDGE ) ;
/*check if the requested attributes are available inside the mesh*/
if ( ! importattribute [ VERTNORMALBO ] & & ! importattribute [ FACENORMALBO ] )
nm = NR_NONE ;
if ( ! importattribute [ VERTCOLORBO ] & & ! importattribute [ FACECOLORBO ] )
cm = CL_NONE ;
if ( ! importattribute [ VERTTEXTUREBO ] & & ! importattribute [ WEDGETEXTUREBO ] )
tm = TX_NONE ;
bool replicated = ( nm = = NR_PERFACE ) | | ( cm = = CL_PERFACE ) | | ( tm = = TX_PERWEDGE ) ;
importattribute [ VERTINDEXBO ] = ! replicated ;
}
2015-06-14 11:39:42 +02:00
void attributesToBeImportedInPointBasedPipeline ( std : : vector < bool > & importattribute , NORMAL_MODALITY nm , COLOR_MODALITY cm ) const
2015-06-04 02:18:35 +02:00
{
importattribute [ VERTPOSITIONBO ] = true ;
importattribute [ VERTNORMALBO ] = vcg : : tri : : HasPerVertexNormal ( _mesh ) & & ( nm = = NR_PERVERT ) ;
importattribute [ FACENORMALBO ] = false ;
importattribute [ VERTCOLORBO ] = vcg : : tri : : HasPerVertexColor ( _mesh ) & & ( cm = = CL_PERVERT ) ;
importattribute [ FACECOLORBO ] = false ;
importattribute [ VERTTEXTUREBO ] = false ;
importattribute [ WEDGETEXTUREBO ] = false ;
importattribute [ VERTINDEXBO ] = false ;
}
2015-06-10 20:13:28 +02:00
bool buffersAllocationFunction ( GLuint & vaohandlespecificperopenglcontext , NORMAL_MODALITY nm , COLOR_MODALITY cm , TEXTURE_MODALITY tm , const std : : vector < bool > & importattribute , std : : vector < bool > & attributestobeupdated )
2015-06-04 02:18:35 +02:00
{
2015-06-14 11:39:42 +02:00
if ( vaohandlespecificperopenglcontext = = 0 )
2015-06-10 20:13:28 +02:00
//glGenVertexArrays(1,&vaohandle);
return false ;
2015-06-04 02:18:35 +02:00
bool replicated = ( importattribute [ FACENORMALBO ] | | importattribute [ FACECOLORBO ] | | importattribute [ WEDGETEXTUREBO ] ) ;
attributestobeupdated . clear ( ) ;
attributestobeupdated . resize ( importattribute . size ( ) ) ;
long long unsigned int bomemoryrequiredbymesh = this - > bufferObjectsMemoryRequired ( nm , cm , tm , importattribute [ VERTINDEXBO ] ) ;
unsigned int ii = 0 ;
for ( typename std : : vector < GLBufferObject * > : : iterator it = _bo . begin ( ) ; it ! = _bo . end ( ) ; + + it )
{
BO_NAMES boname = static_cast < BO_NAMES > ( ii ) ;
size_t sz = boExpectedSize ( boname , replicated , importattribute [ VERTINDEXBO ] ) ;
size_t dim = boExpectedDimension ( boname , replicated , importattribute [ VERTINDEXBO ] ) ;
if ( ( * it ! = NULL ) & & ( ( ! ( * it ) - > _isvalid ) | |
/*if _lastfeedingusedreplicatedpipeline == false means that maybe there are valid per vertex attribute buffer objects that MUST be reallocated anyway cause we have to switch to the replicated attributes pipeline*/
( replicated & & ! _lastfeedingusedreplicatedpipeline & & ( isPerVertexAttribute ( boname ) | | ( boname = = VERTINDEXBO ) ) ) | |
/*we switched back from the replicated pipeline to the normal one. All the bos have to be regenerated*/
( ! replicated & & _lastfeedingusedreplicatedpipeline ) | |
/*the buffer object is valid but for same reason the number of cells of the bo don't suit anymore the required size. we have to reallocate the buffer object*/
( ( ( * it ) - > _isvalid ) & & ( sz ! = ( * it ) - > _size ) ) ) | |
//the buffer is valid, but the attribute is not required to be displayed
( ( ( * it ) - > _isvalid ) & & ! importattribute [ ii ] ) )
{
//disableClientState(boname,importattribute);
/*WARNING! THIS CODE MUST BE INCAPSULATED INTO A DEALLOCATE FUNCTION IN A PROPER MADE BUFFER OBJECT CLASS
I DON ' T INSERT IT INTO THE GLBufferObjectInfo CLASS CAUSE I CONSIDER IT A TEMPORARY PRIVATE STRUCT */
glDeleteBuffers ( 1 , & ( ( * it ) - > _bohandle ) ) ;
( * it ) - > _bohandle = 0 ;
if ( ( * it ) - > _size > 0 )
//we don't use dim cause dim is the value that is going to be allocated, instead use (*it)->_size * (*it)->getSizeOfGLType() is the value already in the buffer
_gpumeminfo . releasedMemory ( ( * it ) - > _size * ( * it ) - > getSizeOfGLType ( ) ) ;
( * it ) - > _isvalid = false ;
( * it ) - > _size = 0 ;
/**********************************************************************************************************/
}
//there are already valid mesh attributes properly allocated in memory, we don't need to allocate them again
if ( ( * it ! = NULL ) & & ( ( ( * it ) - > _isvalid ) & & ( sz = = ( * it ) - > _size ) ) )
bomemoryrequiredbymesh - = dim ;
+ + ii ;
}
if ( ! _gpumeminfo . isAdditionalMemoryAvailable ( bomemoryrequiredbymesh ) )
{
std : : cout < < " no additional memory available!!! memory required: " < < bomemoryrequiredbymesh < < std : : endl ;
ii = 0 ;
for ( typename std : : vector < GLBufferObject * > : : iterator it = _bo . begin ( ) ; it ! = _bo . end ( ) ; + + it )
{
BO_NAMES boname = static_cast < BO_NAMES > ( ii ) ;
size_t sz ( boExpectedSize ( boname , replicated , importattribute [ VERTINDEXBO ] ) ) ;
//there are already valid mesh attributes properly allocated in memory but there is not enough gpu memory for the remaining mesh.
//we have to deallocate the previously allocated mesh attributes
if ( ( * it ! = NULL ) & & ( ( ( * it ) - > _isvalid ) & & ( sz = = ( * it ) - > _size ) ) )
{
long long unsigned int dim ( boExpectedDimension ( boname , replicated , importattribute [ VERTINDEXBO ] ) ) ;
//disableClientState(boname,importattribute);
if ( ( * it ) - > _size > 0 )
{
/*WARNING! THIS CODE MUST BE INCAPSULATED INTO A DEALLOCATE FUNCTION IN A PROPER MADE BUFFER OBJECT CLASS
I DON ' T INSERT IT INTO THE GLBufferObjectInfo CLASS CAUSE I CONSIDER IT A TEMPORARY PRIVATE STRUCT */
glDeleteBuffers ( 1 , & ( * it ) - > _bohandle ) ;
( * it ) - > _bohandle = 0 ;
_gpumeminfo . releasedMemory ( dim ) ;
}
( * it ) - > _isvalid = false ;
( * it ) - > _size = 0 ;
/*********************************************************************************************************/
}
+ + ii ;
}
_borendering = false ;
_lastfeedingusedreplicatedpipeline = false ;
return false ;
}
else
2015-06-14 11:39:42 +02:00
{
2015-06-04 02:18:35 +02:00
unsigned int ii = 0 ;
//I have to update the invalid buffers requested to be imported
attributestobeupdated = importattribute ;
for ( typename std : : vector < GLBufferObject * > : : iterator it = _bo . begin ( ) ; it ! = _bo . end ( ) ; + + it )
{
BO_NAMES boname = static_cast < BO_NAMES > ( ii ) ;
GLBufferObject * cbo = _bo . at ( boname ) ;
bool importatt = importattribute . at ( boname ) ;
2015-06-10 20:13:28 +02:00
glBindVertexArray ( vaohandlespecificperopenglcontext ) ;
2015-06-04 02:18:35 +02:00
bool notvalidbuttoberegenerated = ( cbo ! = NULL ) & & ( ! cbo - > _isvalid ) & & ( importatt ) ;
if ( notvalidbuttoberegenerated )
{
cbo - > _size = boExpectedSize ( boname , replicated , importattribute [ VERTINDEXBO ] ) ;
long long unsigned int dim = boExpectedDimension ( boname , replicated , importattribute [ VERTINDEXBO ] ) ;
glGenBuffers ( 1 , & cbo - > _bohandle ) ;
2015-06-14 11:39:42 +02:00
glBindBuffer ( cbo - > _target , cbo - > _bohandle ) ;
glBufferData ( cbo - > _target , dim , NULL , GL_STATIC_DRAW ) ;
2015-06-04 02:18:35 +02:00
setBufferPointerEnableClientState ( boname ) ;
2015-06-14 11:39:42 +02:00
glBindBuffer ( cbo - > _target , 0 ) ;
_gpumeminfo . acquiredMemory ( dim ) ;
2015-06-04 02:18:35 +02:00
attributestobeupdated [ boname ] = true ;
cbo - > _isvalid = true ;
}
else
{
attributestobeupdated [ boname ] = false ;
if ( ! importatt )
cbo - > _isvalid = false ;
}
if ( ( cbo = = NULL ) | | ( ! cbo - > _isvalid ) )
{
//glBindVertexArray(_vaohandle);
disableClientState ( boname , importattribute ) ;
//glBindVertexArray(0);
}
+ + ii ;
glBindVertexArray ( 0 ) ;
}
_borendering = true ;
_lastfeedingusedreplicatedpipeline = replicated ;
return true ;
}
}
2015-06-14 11:39:42 +02:00
bool tryToAllocatePerTriangleAttributesInBO ( GLuint & vaohandlespecificperopenglcontext , NORMAL_MODALITY nm , COLOR_MODALITY cm , TEXTURE_MODALITY tm )
{
std : : vector < bool > importattribute ( _bo . size ( ) ) ;
std : : vector < bool > attributestobeupdated ;
attributesToBeImportedInTriangleBasedPipeline ( importattribute , nm , cm , tm ) ;
bool replicated = ! importattribute [ VERTINDEXBO ] ;
bool immediatemode = ! ( buffersAllocationFunction ( vaohandlespecificperopenglcontext , nm , cm , tm , importattribute , attributestobeupdated ) ) ;
if ( immediatemode )
return false ;
bool somethingtoupdate = false ;
for ( size_t hh = 0 ; hh < attributestobeupdated . size ( ) ; + + hh )
somethingtoupdate = somethingtoupdate | | attributestobeupdated [ hh ] ;
if ( somethingtoupdate )
{
if ( replicated )
{
//WARNING!In case we have to update the wedgetexture bo maybe (not always!) we must update also the other buffer already in memory
//cause the wedgetexture pipeline force a change in the order of the triangles in GPU.
//they are now ordered by the texture seam and not more by the triangle index!
if ( attributestobeupdated [ WEDGETEXTUREBO ] )
{
for ( size_t jj = 0 ; jj < attributestobeupdated . size ( ) ; + + jj )
attributestobeupdated [ jj ] = importattribute [ jj ] | | attributestobeupdated [ jj ] ;
}
updateBuffersReplicatedPipeline ( attributestobeupdated , tm ) ;
}
else
updateBuffersIndexedPipeline ( attributestobeupdated ) ;
}
return true ;
}
bool tryToAllocatePerPointAttributesInBO ( GLuint & vaohandlespecificperopenglcontext , NORMAL_MODALITY nm , COLOR_MODALITY cm )
{
std : : vector < bool > importattribute ( _bo . size ( ) ) ;
std : : vector < bool > attributestobeupdated ;
attributesToBeImportedInPointBasedPipeline ( importattribute , nm , cm ) ;
bool immediatemode = ! ( buffersAllocationFunction ( vaohandlespecificperopenglcontext , nm , cm , TX_NONE , importattribute , attributestobeupdated ) ) ;
if ( immediatemode )
return false ;
bool somethingtoupdate = false ;
for ( size_t hh = 0 ; hh < attributestobeupdated . size ( ) ; + + hh )
somethingtoupdate = somethingtoupdate | | attributestobeupdated [ hh ] ;
if ( somethingtoupdate )
updateBuffersIndexedPipeline ( attributestobeupdated ) ;
return true ;
}
2015-06-04 02:18:35 +02:00
bool updateBuffersIndexedPipeline ( const std : : vector < bool > & attributestobeupdated )
{
_chunkmap . clear ( ) ;
size_t vn = _mesh . vn ;
size_t tn = _mesh . fn ;
size_t facechunk = std : : min ( size_t ( tn ) , _perbatchsimplex ) ;
size_t vertexchunk = std : : min ( size_t ( vn ) , _perbatchsimplex ) ;
std : : vector < vcg : : Point3f > pv ( vertexchunk ) ;
std : : vector < vcg : : Point3f > nv ( vertexchunk ) ;
std : : vector < vcg : : Color4b > cv ( vertexchunk ) ; // Per vertex Colors
std : : vector < float > tv ( vertexchunk * 2 ) ;
size_t chunckingpu = 0 ;
for ( size_t i = 0 ; i < vn ; + + i )
{
size_t chunckindex = i % vertexchunk ;
if ( attributestobeupdated [ VERTPOSITIONBO ] )
pv [ chunckindex ] . Import ( _mesh . vert [ i ] . cP ( ) ) ;
if ( attributestobeupdated [ VERTNORMALBO ] )
{
nv [ chunckindex ] . Import ( _mesh . vert [ i ] . cN ( ) ) ;
nv [ chunckindex ] . Normalize ( ) ;
}
if ( attributestobeupdated [ VERTCOLORBO ] )
cv [ chunckindex ] = _mesh . vert [ i ] . cC ( ) ;
if ( attributestobeupdated [ VERTTEXTUREBO ] )
{
tv [ chunckindex * 2 + 0 ] = _mesh . vert [ i ] . cT ( ) . U ( ) ;
tv [ chunckindex * 2 + 1 ] = _mesh . vert [ i ] . cT ( ) . V ( ) ;
}
if ( ( i = = vn - 1 ) | | ( chunckindex = = vertexchunk - 1 ) )
{
size_t chuncksize = vertexchunk ;
if ( i = = vn - 1 )
chuncksize = chunckindex + 1 ;
if ( attributestobeupdated [ VERTPOSITIONBO ] )
{
GLBufferObject * buffobj = _bo [ VERTPOSITIONBO ] ;
glBindBuffer ( GL_ARRAY_BUFFER , buffobj - > _bohandle ) ;
glBufferSubData ( GL_ARRAY_BUFFER , chunckingpu * vertexchunk * buffobj - > _components * buffobj - > getSizeOfGLType ( ) , buffobj - > _components * buffobj - > getSizeOfGLType ( ) * chuncksize , & pv [ 0 ] ) ;
glBindBuffer ( GL_ARRAY_BUFFER , 0 ) ;
}
if ( attributestobeupdated [ VERTNORMALBO ] )
{
GLBufferObject * buffobj = _bo [ VERTNORMALBO ] ;
glBindBuffer ( GL_ARRAY_BUFFER , buffobj - > _bohandle ) ;
glBufferSubData ( GL_ARRAY_BUFFER , chunckingpu * vertexchunk * buffobj - > _components * buffobj - > getSizeOfGLType ( ) , buffobj - > _components * buffobj - > getSizeOfGLType ( ) * chuncksize , & nv [ 0 ] ) ;
glBindBuffer ( GL_ARRAY_BUFFER , 0 ) ;
}
if ( attributestobeupdated [ VERTCOLORBO ] )
{
GLBufferObject * buffobj = _bo [ VERTCOLORBO ] ;
glBindBuffer ( GL_ARRAY_BUFFER , buffobj - > _bohandle ) ;
glBufferSubData ( GL_ARRAY_BUFFER , chunckingpu * vertexchunk * buffobj - > _components * buffobj - > getSizeOfGLType ( ) , buffobj - > _components * buffobj - > getSizeOfGLType ( ) * chuncksize , & cv [ 0 ] ) ;
glBindBuffer ( GL_ARRAY_BUFFER , 0 ) ;
}
if ( attributestobeupdated [ VERTTEXTUREBO ] )
{
GLBufferObject * buffobj = _bo [ VERTTEXTUREBO ] ;
glBindBuffer ( GL_ARRAY_BUFFER , buffobj - > _bohandle ) ;
glBufferSubData ( GL_ARRAY_BUFFER , chunckingpu * vertexchunk * buffobj - > _components * buffobj - > getSizeOfGLType ( ) , buffobj - > _components * buffobj - > getSizeOfGLType ( ) * chuncksize , & tv [ 0 ] ) ;
glBindBuffer ( GL_ARRAY_BUFFER , 0 ) ;
}
+ + chunckingpu ;
}
}
pv . clear ( ) ;
nv . clear ( ) ;
cv . clear ( ) ;
tv . clear ( ) ;
chunckingpu = 0 ;
std : : vector < GLuint > ti ( facechunk * 3 ) ;
for ( size_t i = 0 ; i < tn ; + + i )
{
size_t chunckindex = i % facechunk ;
ti [ chunckindex * 3 + 0 ] = GLuint ( vcg : : tri : : Index ( _mesh , _mesh . face [ i ] . V ( 0 ) ) ) ;
ti [ chunckindex * 3 + 1 ] = GLuint ( vcg : : tri : : Index ( _mesh , _mesh . face [ i ] . V ( 1 ) ) ) ;
ti [ chunckindex * 3 + 2 ] = GLuint ( vcg : : tri : : Index ( _mesh , _mesh . face [ i ] . V ( 2 ) ) ) ;
if ( ( i = = tn - 1 ) | | ( chunckindex = = facechunk - 1 ) )
{
size_t chunksize = facechunk ;
if ( i = = tn - 1 )
chunksize = chunckindex + 1 ;
if ( attributestobeupdated [ VERTINDEXBO ] )
{
glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER , _bo [ VERTINDEXBO ] - > _bohandle ) ;
glBufferSubData ( GL_ELEMENT_ARRAY_BUFFER , chunckingpu * facechunk * _bo [ VERTINDEXBO ] - > _components * _bo [ VERTINDEXBO ] - > getSizeOfGLType ( ) , _bo [ VERTINDEXBO ] - > _components * _bo [ VERTINDEXBO ] - > getSizeOfGLType ( ) * chunksize , & ti [ 0 ] ) ;
glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER , 0 ) ;
}
+ + chunckingpu ;
}
}
return true ;
}
bool updateBuffersReplicatedPipeline ( const std : : vector < bool > & attributestobeupdated , GLFeedEnum : : TEXTURE_MODALITY currtextmod )
{
size_t tn = _mesh . fn ;
size_t facechunk = std : : min ( size_t ( tn ) , _perbatchsimplex ) ;
std : : vector < vcg : : Point3f > rpv ( facechunk * 3 ) ;
std : : vector < vcg : : Point3f > rnv ( facechunk * 3 ) ;
std : : vector < vcg : : Color4b > rcv ( facechunk * 3 ) ;
std : : vector < float > rtv ( facechunk * 3 * 2 ) ;
size_t chunckingpu = 0 ;
//it's a map containing for each texture seams n a vector of all the triangle index ranges having n has texture seam
//Suppose that in a mesh we have
//TXS_0{t0,t1,t2,t3}, TXS_4{t4,t5},TXS_0{t6},TXS_-1{t7,t8,t9},TXS_4{t10,t11}
//so chunkMap will contain
// -1 -> [<t7,t9>]
// 0 -> [<t0,t3>,<t6,t6>]
// 4 -> [<t4,t5>,<t10,t11>]
//
//if the map has no-texture coords at all in order to unify the code we fill the ChunkMap with texture seam -1 and a single triangle range going from face_0 to face_n-1
if ( attributestobeupdated [ WEDGETEXTUREBO ] | | attributestobeupdated [ VERTTEXTUREBO ] )
{
_chunkmap . clear ( ) ;
if ( attributestobeupdated [ WEDGETEXTUREBO ] )
fillChunckMap ( _chunkmap ) ;
else
if ( attributestobeupdated [ VERTTEXTUREBO ] )
_chunkmap [ 0 ] . push_back ( std : : make_pair ( 0 , tn - 1 ) ) ;
}
//default case: no texture is required to be rendered but a non texture attribute has to be updated
//we have to init the _chunkmap with just one entry (-1...that means no texture) referring all the triangles in the mesh
if ( ( currtextmod = = GLFeedEnum : : TX_NONE ) & &
( attributestobeupdated [ VERTPOSITIONBO ] | |
attributestobeupdated [ VERTNORMALBO ] | | attributestobeupdated [ FACENORMALBO ] | |
attributestobeupdated [ VERTCOLORBO ] | | attributestobeupdated [ FACECOLORBO ] ) )
{
_chunkmap . clear ( ) ;
_chunkmap [ - 1 ] . push_back ( std : : make_pair ( 0 , tn - 1 ) ) ;
}
int t = 0 ;
if ( attributestobeupdated [ WEDGETEXTUREBO ] | | attributestobeupdated [ VERTTEXTUREBO ] )
{
_texindnumtriangles . clear ( ) ;
_texindnumtriangles . resize ( _chunkmap . size ( ) ) ;
}
int i = 0 ;
size_t chunkindex = i ;
GLuint triangles = 0 ;
for ( ChunkMap : : const_iterator mit = _chunkmap . begin ( ) ; mit ! = _chunkmap . end ( ) ; + + mit )
{
for ( ChunkVector : : const_iterator cit = mit - > second . begin ( ) ; cit ! = mit - > second . end ( ) ; + + cit )
{
for ( size_t indf = cit - > first ; indf < = cit - > second ; + + indf )
{
chunkindex = i % facechunk ;
if ( attributestobeupdated [ VERTPOSITIONBO ] )
{
rpv [ chunkindex * 3 + 0 ] . Import ( _mesh . face [ indf ] . V ( 0 ) - > P ( ) ) ;
rpv [ chunkindex * 3 + 1 ] . Import ( _mesh . face [ indf ] . V ( 1 ) - > P ( ) ) ;
rpv [ chunkindex * 3 + 2 ] . Import ( _mesh . face [ indf ] . V ( 2 ) - > P ( ) ) ;
}
if ( attributestobeupdated [ VERTNORMALBO ] )
{
rnv [ chunkindex * 3 + 0 ] . Import ( _mesh . face [ indf ] . V ( 0 ) - > N ( ) . Normalize ( ) ) ;
rnv [ chunkindex * 3 + 1 ] . Import ( _mesh . face [ indf ] . V ( 1 ) - > N ( ) . Normalize ( ) ) ;
rnv [ chunkindex * 3 + 2 ] . Import ( _mesh . face [ indf ] . V ( 2 ) - > N ( ) . Normalize ( ) ) ;
}
else if ( attributestobeupdated [ FACENORMALBO ] )
{
rnv [ chunkindex * 3 + 0 ] . Import ( _mesh . face [ indf ] . N ( ) . Normalize ( ) ) ;
rnv [ chunkindex * 3 + 1 ] . Import ( _mesh . face [ indf ] . N ( ) . Normalize ( ) ) ;
rnv [ chunkindex * 3 + 2 ] . Import ( _mesh . face [ indf ] . N ( ) . Normalize ( ) ) ;
}
if ( ( attributestobeupdated [ VERTCOLORBO ] ) )
{
rcv [ chunkindex * 3 + 0 ] = _mesh . face [ indf ] . V ( 0 ) - > C ( ) ;
rcv [ chunkindex * 3 + 1 ] = _mesh . face [ indf ] . V ( 1 ) - > C ( ) ;
rcv [ chunkindex * 3 + 2 ] = _mesh . face [ indf ] . V ( 2 ) - > C ( ) ;
}
else if ( ( attributestobeupdated [ FACECOLORBO ] ) )
{
rcv [ chunkindex * 3 + 0 ] = _mesh . face [ indf ] . C ( ) ;
rcv [ chunkindex * 3 + 1 ] = _mesh . face [ indf ] . C ( ) ;
rcv [ chunkindex * 3 + 2 ] = _mesh . face [ indf ] . C ( ) ;
}
if ( attributestobeupdated [ WEDGETEXTUREBO ] )
{
rtv [ chunkindex * 6 + 0 ] = float ( _mesh . face [ indf ] . WT ( 0 ) . U ( ) ) ;
rtv [ chunkindex * 6 + 1 ] = float ( _mesh . face [ indf ] . WT ( 0 ) . V ( ) ) ;
rtv [ chunkindex * 6 + 2 ] = float ( _mesh . face [ indf ] . WT ( 1 ) . U ( ) ) ;
rtv [ chunkindex * 6 + 3 ] = float ( _mesh . face [ indf ] . WT ( 1 ) . V ( ) ) ;
rtv [ chunkindex * 6 + 4 ] = float ( _mesh . face [ indf ] . WT ( 2 ) . U ( ) ) ;
rtv [ chunkindex * 6 + 5 ] = float ( _mesh . face [ indf ] . WT ( 2 ) . V ( ) ) ;
}
else if ( attributestobeupdated [ VERTTEXTUREBO ] )
{
rtv [ chunkindex * 6 + 0 ] = float ( _mesh . face [ indf ] . V ( 0 ) - > T ( ) . U ( ) ) ;
rtv [ chunkindex * 6 + 1 ] = float ( _mesh . face [ indf ] . V ( 0 ) - > T ( ) . V ( ) ) ;
rtv [ chunkindex * 6 + 2 ] = float ( _mesh . face [ indf ] . V ( 1 ) - > T ( ) . U ( ) ) ;
rtv [ chunkindex * 6 + 3 ] = float ( _mesh . face [ indf ] . V ( 1 ) - > T ( ) . V ( ) ) ;
rtv [ chunkindex * 6 + 4 ] = float ( _mesh . face [ indf ] . V ( 2 ) - > T ( ) . U ( ) ) ;
rtv [ chunkindex * 6 + 5 ] = float ( _mesh . face [ indf ] . V ( 2 ) - > T ( ) . V ( ) ) ;
}
if ( ( i = = tn - 1 ) | | ( chunkindex = = facechunk - 1 ) )
{
size_t chunksize = facechunk ;
if ( i = = tn - 1 )
chunksize = chunkindex + 1 ;
if ( attributestobeupdated [ VERTPOSITIONBO ] )
{
GLBufferObject * buffobj = _bo [ VERTPOSITIONBO ] ;
glBindBuffer ( GL_ARRAY_BUFFER , buffobj - > _bohandle ) ;
glBufferSubData ( GL_ARRAY_BUFFER , chunckingpu * facechunk * 3 * buffobj - > _components * buffobj - > getSizeOfGLType ( ) , 3 * buffobj - > _components * buffobj - > getSizeOfGLType ( ) * chunksize , & rpv [ 0 ] ) ;
glBindBuffer ( GL_ARRAY_BUFFER , 0 ) ;
}
if ( attributestobeupdated [ VERTNORMALBO ] | | attributestobeupdated [ FACENORMALBO ] )
{
GLBufferObject * buffobj ;
if ( attributestobeupdated [ VERTNORMALBO ] )
buffobj = _bo [ VERTNORMALBO ] ;
else
buffobj = _bo [ FACENORMALBO ] ;
glBindBuffer ( GL_ARRAY_BUFFER , buffobj - > _bohandle ) ;
glBufferSubData ( GL_ARRAY_BUFFER , chunckingpu * facechunk * 3 * buffobj - > _components * buffobj - > getSizeOfGLType ( ) , 3 * buffobj - > _components * buffobj - > getSizeOfGLType ( ) * chunksize , & rnv [ 0 ] ) ;
glBindBuffer ( GL_ARRAY_BUFFER , 0 ) ;
}
if ( attributestobeupdated [ VERTCOLORBO ] | | attributestobeupdated [ FACECOLORBO ] )
{
GLBufferObject * buffobj ;
if ( attributestobeupdated [ VERTCOLORBO ] )
buffobj = _bo [ VERTCOLORBO ] ;
else
buffobj = _bo [ FACECOLORBO ] ;
glBindBuffer ( GL_ARRAY_BUFFER , buffobj - > _bohandle ) ;
glBufferSubData ( GL_ARRAY_BUFFER , chunckingpu * facechunk * 3 * buffobj - > _components * buffobj - > getSizeOfGLType ( ) , 3 * buffobj - > _components * buffobj - > getSizeOfGLType ( ) * chunksize , & rcv [ 0 ] ) ;
glBindBuffer ( GL_ARRAY_BUFFER , 0 ) ;
}
if ( attributestobeupdated [ VERTTEXTUREBO ] | | attributestobeupdated [ WEDGETEXTUREBO ] )
{
GLBufferObject * buffobj ;
if ( attributestobeupdated [ VERTTEXTUREBO ] )
buffobj = _bo [ VERTTEXTUREBO ] ;
else
buffobj = _bo [ WEDGETEXTUREBO ] ;
glBindBuffer ( GL_ARRAY_BUFFER , buffobj - > _bohandle ) ;
glBufferSubData ( GL_ARRAY_BUFFER , chunckingpu * facechunk * 3 * buffobj - > _components * buffobj - > getSizeOfGLType ( ) , 3 * buffobj - > _components * buffobj - > getSizeOfGLType ( ) * chunksize , & rtv [ 0 ] ) ;
glBindBuffer ( GL_ARRAY_BUFFER , 0 ) ;
}
+ + chunckingpu ;
}
+ + i ;
}
triangles + = cit - > second - cit - > first + 1 ;
}
if ( attributestobeupdated [ WEDGETEXTUREBO ] | | attributestobeupdated [ VERTTEXTUREBO ] )
_texindnumtriangles [ t ] = std : : make_pair ( mit - > first , triangles ) ;
+ + t ;
}
//return (k != tn)
// throw MeshLabException("Mesh has not been properly partitioned");
return true ;
}
2015-06-14 11:39:42 +02:00
bool immediateMode ( NORMAL_MODALITY nm , COLOR_MODALITY cm , TEXTURE_MODALITY tm , const std : : vector < GLuint > & textureindex = std : : vector < GLuint > ( ) )
2015-06-04 02:18:35 +02:00
{
glPushAttrib ( GL_ALL_ATTRIB_BITS ) ;
if ( _mesh . fn = = 0 )
return false ;
if ( cm = = CL_PERMESH )
glColor ( _mesh . C ( ) ) ;
//typename MESHTYPE::FaceContainer::iterator fp;
typename MESHTYPE : : FaceIterator fi = _mesh . face . begin ( ) ;
short curtexname = - 1 ;
if ( tm = = TX_PERWEDGE )
{
curtexname = ( * fi ) . WT ( 0 ) . n ( ) ;
if ( ( curtexname > = 0 ) & & ( curtexname < ( int ) textureindex . size ( ) ) )
{
glEnable ( GL_TEXTURE_2D ) ;
glBindTexture ( GL_TEXTURE_2D , textureindex [ curtexname ] ) ;
}
else
{
glDisable ( GL_TEXTURE_2D ) ;
}
}
if ( tm = = TX_PERVERT & & ! textureindex . empty ( ) ) // in the case of per vertex tex coord we assume that we have a SINGLE texture.
{
curtexname = 0 ;
glEnable ( GL_TEXTURE_2D ) ;
glBindTexture ( GL_TEXTURE_2D , textureindex [ curtexname ] ) ;
}
glBegin ( GL_TRIANGLES ) ;
while ( fi ! = _mesh . face . end ( ) )
{
typename MESHTYPE : : FaceType & f = * fi ;
if ( ! f . IsD ( ) )
{
if ( tm = = TX_PERWEDGE )
if ( f . WT ( 0 ) . n ( ) ! = curtexname )
{
curtexname = ( * fi ) . WT ( 0 ) . n ( ) ;
glEnd ( ) ;
if ( curtexname > = 0 )
{
glEnable ( GL_TEXTURE_2D ) ;
if ( ! textureindex . empty ( ) )
glBindTexture ( GL_TEXTURE_2D , textureindex [ curtexname ] ) ;
}
else
{
glDisable ( GL_TEXTURE_2D ) ;
}
glBegin ( GL_TRIANGLES ) ;
}
if ( nm = = NR_PERFACE ) glNormal ( f . cN ( ) ) ;
if ( nm = = NR_PERVERT ) glNormal ( f . V ( 0 ) - > cN ( ) ) ;
//if(nm == NMPerWedge)glNormal(f.WN(0));
if ( cm = = CL_PERFACE ) glColor ( f . C ( ) ) ;
if ( cm = = CL_PERVERT ) glColor ( f . V ( 0 ) - > C ( ) ) ;
if ( tm = = TX_PERVERT ) glTexCoord ( f . V ( 0 ) - > T ( ) . P ( ) ) ;
if ( tm = = TX_PERWEDGE ) glTexCoord ( f . WT ( 0 ) . t ( 0 ) ) ;
glVertex ( f . V ( 0 ) - > P ( ) ) ;
if ( nm = = NR_PERVERT ) glNormal ( f . V ( 1 ) - > cN ( ) ) ;
//if(nm == NMPerWedge)glNormal(f.WN(1));
if ( cm = = CL_PERVERT ) glColor ( f . V ( 1 ) - > C ( ) ) ;
if ( tm = = TX_PERVERT ) glTexCoord ( f . V ( 1 ) - > T ( ) . P ( ) ) ;
if ( tm = = TX_PERWEDGE ) glTexCoord ( f . WT ( 1 ) . t ( 0 ) ) ;
glVertex ( f . V ( 1 ) - > P ( ) ) ;
if ( nm = = NR_PERVERT ) glNormal ( f . V ( 2 ) - > cN ( ) ) ;
//if(nm == NMPerWedge)glNormal(f.WN(2));
if ( cm = = CL_PERVERT ) glColor ( f . V ( 2 ) - > C ( ) ) ;
if ( tm = = TX_PERVERT ) glTexCoord ( f . V ( 2 ) - > T ( ) . P ( ) ) ;
if ( tm = = TX_PERWEDGE ) glTexCoord ( f . WT ( 2 ) . t ( 0 ) ) ;
glVertex ( f . V ( 2 ) - > P ( ) ) ;
}
+ + fi ;
}
glEnd ( ) ;
glPopMatrix ( ) ;
glPopAttrib ( ) ;
return true ;
}
2015-06-10 20:13:28 +02:00
bool drawTriangles ( GLuint & vaohandlespecificperopenglcontext , NORMAL_MODALITY nm , COLOR_MODALITY cm , TEXTURE_MODALITY tm , const std : : vector < GLuint > & textureindex )
2015-06-04 02:18:35 +02:00
{
std : : vector < bool > att ( _bo . size ( ) , false ) ;
attributesToBeImportedInTriangleBasedPipeline ( att , nm , cm , tm ) ;
bool replicated = ! att [ VERTINDEXBO ] ;
2015-06-14 11:39:42 +02:00
GLenum err = glGetError ( ) ;
assert ( err = = GL_NO_ERROR ) ;
2015-06-10 20:13:28 +02:00
glBindVertexArray ( vaohandlespecificperopenglcontext ) ;
2015-06-14 11:39:42 +02:00
err = glGetError ( ) ;
assert ( err = = GL_NO_ERROR ) ;
2015-06-04 02:18:35 +02:00
if ( replicated )
{
int firsttriangleoffset = 0 ;
if ( tm = = GLFeedEnum : : TX_NONE )
{
glDisable ( GL_TEXTURE_2D ) ;
glDrawArrays ( GL_TRIANGLES , 0 , _mesh . fn * 3 ) ;
}
else
{
glEnable ( GL_TEXTURE_2D ) ;
for ( std : : vector < std : : pair < short , GLuint > > : : const_iterator it = _texindnumtriangles . begin ( ) ; it ! = _texindnumtriangles . end ( ) ; + + it )
{
if ( ( it - > first ! = - 1 ) & & ( it - > first < textureindex . size ( ) ) )
glBindTexture ( GL_TEXTURE_2D , textureindex [ it - > first ] ) ;
else
glBindTexture ( GL_TEXTURE_2D , 0 ) ;
glDrawArrays ( GL_TRIANGLES , firsttriangleoffset , it - > second * 3 - firsttriangleoffset ) ;
firsttriangleoffset = it - > second * 3 ;
}
glBindTexture ( GL_TEXTURE_2D , 0 ) ;
glDisable ( GL_TEXTURE_2D ) ;
}
}
else
{
if ( tm = = TX_PERVERT )
{
if ( textureindex . size ( ) > 0 )
{
glEnable ( GL_TEXTURE_2D ) ;
glBindTexture ( GL_TEXTURE_2D , textureindex [ 0 ] ) ;
}
}
else
glDisable ( GL_TEXTURE_2D ) ;
if ( _bo [ VERTINDEXBO ] - > _isvalid )
{
2015-06-14 11:39:42 +02:00
err = glGetError ( ) ;
assert ( err = = GL_NO_ERROR ) ;
2015-06-04 02:18:35 +02:00
glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER , _bo [ VERTINDEXBO ] - > _bohandle ) ;
2015-06-14 11:39:42 +02:00
err = glGetError ( ) ;
assert ( err = = GL_NO_ERROR ) ;
glDrawElements ( GL_TRIANGLES , _mesh . fn * _bo [ VERTINDEXBO ] - > _components , GL_UNSIGNED_INT , NULL ) ;
err = glGetError ( ) ;
printf ( " errore (%s) \n " , gluErrorString ( err ) ) ;
assert ( err = = GL_NO_ERROR ) ;
glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER , 0 ) ;
err = glGetError ( ) ;
assert ( err = = GL_NO_ERROR ) ;
2015-06-04 02:18:35 +02:00
}
glBindTexture ( GL_TEXTURE_2D , 0 ) ;
glDisable ( GL_TEXTURE_2D ) ;
}
glBindVertexArray ( 0 ) ;
glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER , 0 ) ;
glBindBuffer ( GL_ARRAY_BUFFER , 0 ) ;
return true ;
}
2015-06-10 20:13:28 +02:00
void drawPoints ( GLuint & vaohandlespecificperopenglcontext )
2015-06-04 02:18:35 +02:00
{
glDisable ( GL_TEXTURE_2D ) ;
2015-06-10 20:13:28 +02:00
glBindVertexArray ( vaohandlespecificperopenglcontext ) ;
2015-06-04 02:18:35 +02:00
glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER , _bo [ VERTINDEXBO ] - > _bohandle ) ;
glDrawArrays ( GL_POINTS , 0 , _mesh . vn ) ;
glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER , 0 ) ;
glBindVertexArray ( 0 ) ;
}
2015-06-14 11:39:42 +02:00
void setBufferPointerEnableClientState ( BO_NAMES boname ) const
2015-06-04 02:18:35 +02:00
{
if ( ( boname < VERTPOSITIONBO ) | | ( boname > VERTINDEXBO ) )
return ;
GLBufferObject * cbo = _bo [ boname ] ;
if ( cbo = = NULL )
return ;
switch ( boname )
{
case ( VERTPOSITIONBO ) :
{
glVertexPointer ( cbo - > _components , cbo - > _gltype , 0 , 0 ) ;
glEnableClientState ( GL_VERTEX_ARRAY ) ;
break ;
}
case ( VERTNORMALBO ) :
case ( FACENORMALBO ) :
{
glNormalPointer ( cbo - > _gltype , 0 , 0 ) ;
glEnableClientState ( GL_NORMAL_ARRAY ) ;
break ;
}
case ( VERTCOLORBO ) :
case ( FACECOLORBO ) :
{
glColorPointer ( cbo - > _components , cbo - > _gltype , 0 , 0 ) ;
glEnableClientState ( GL_COLOR_ARRAY ) ;
break ;
}
case ( VERTTEXTUREBO ) :
case ( WEDGETEXTUREBO ) :
{
glTexCoordPointer ( cbo - > _components , cbo - > _gltype , 0 , 0 ) ;
glEnableClientState ( GL_TEXTURE_COORD_ARRAY ) ;
break ;
}
case ( VERTINDEXBO ) :
{
2015-06-14 11:39:42 +02:00
break ;
2015-06-04 02:18:35 +02:00
}
}
}
2015-06-14 11:39:42 +02:00
void disableClientState ( BO_NAMES boname , const std : : vector < bool > & importatt ) const
2015-06-04 02:18:35 +02:00
{
if ( ( boname < VERTPOSITIONBO ) | | ( boname > VERTINDEXBO ) )
return ;
switch ( boname )
{
case ( VERTPOSITIONBO ) :
{
glDisableClientState ( GL_VERTEX_ARRAY ) ;
break ;
}
case ( VERTNORMALBO ) :
case ( FACENORMALBO ) :
{
if ( ! importatt [ VERTNORMALBO ] & & ! importatt [ FACENORMALBO ] )
glDisableClientState ( GL_NORMAL_ARRAY ) ;
break ;
}
case ( VERTCOLORBO ) :
case ( FACECOLORBO ) :
{
if ( ! importatt [ VERTCOLORBO ] & & ! importatt [ FACECOLORBO ] )
glDisableClientState ( GL_COLOR_ARRAY ) ;
break ;
}
case ( VERTTEXTUREBO ) :
case ( WEDGETEXTUREBO ) :
{
if ( ! importatt [ VERTTEXTUREBO ] & & ! importatt [ WEDGETEXTUREBO ] )
glDisableClientState ( GL_TEXTURE_COORD_ARRAY ) ;
break ;
}
case ( VERTINDEXBO ) :
{
break ;
}
}
}
//expected number of cells should have a the named bo
//generateindex is true when i have a triangle based mesh
// is false when i have a point based mesh
size_t boExpectedSize ( BO_NAMES name , bool replicatedpipeline , bool generateindex ) const
{
try
{
GLBufferObject & cbo = * _bo . at ( name ) ;
size_t vertnum ( _mesh . VN ( ) ) ;
size_t facenum ( _mesh . FN ( ) ) ;
switch ( name )
{
case ( VERTPOSITIONBO ) :
case ( VERTNORMALBO ) :
case ( VERTCOLORBO ) :
case ( VERTTEXTUREBO ) :
{
if ( replicatedpipeline )
return facenum * 3 * cbo . _components ;
else
return vertnum * cbo . _components ;
}
case ( FACENORMALBO ) :
case ( FACECOLORBO ) :
case ( WEDGETEXTUREBO ) :
{
if ( replicatedpipeline )
return facenum * 3 * cbo . _components ;
else
return 0 ;
}
case ( VERTINDEXBO ) :
{
if ( replicatedpipeline | | ! generateindex )
return 0 ;
else
return facenum * cbo . _components ;
}
}
}
catch ( std : : out_of_range & /*exc*/ )
{
return 0 ;
}
return 0 ;
}
//generateindex is true when i have a triangle based mesh
// is false when i have a point based mesh
size_t boExpectedDimension ( BO_NAMES name , bool replicatedpipeline , bool generateindex ) const
{
try
{
size_t sz = boExpectedSize ( name , replicatedpipeline , generateindex ) ;
GLBufferObject & cbo = * _bo . at ( name ) ;
return sz * cbo . getSizeOfGLType ( ) ;
}
catch ( std : : out_of_range & /*exc*/ )
{
return 0 ;
}
return 0 ;
}
static bool isPerVertexAttribute ( BO_NAMES name )
{
return ( ( name = = VERTPOSITIONBO ) | | ( name = = VERTNORMALBO ) | | ( name = = VERTCOLORBO ) | | ( name = = VERTTEXTUREBO ) ) ;
}
//it's a map containing for each texture seams n a vector of all the triangle index ranges having n has texture seam
//Suppose that in a mesh we have
//TXS_0{t0,t1,t2,t3}, TXS_4{t4,t5},TXS_0{t6},TXS_-1{t7,t8,t9},TXS_4{t10,t11}
//so chunkMap will contain
// -1 -> [<t7,t9>]
// 0 -> [<t0,t3>,<t6,t6>]
// 4 -> [<t4,t5>,<t10,t11>]
typedef std : : vector < std : : pair < GLuint , GLuint > > ChunkVector ;
typedef std : : map < short , ChunkVector > ChunkMap ;
void fillChunckMap ( ChunkMap & cmap )
{
if ( ! vcg : : tri : : HasPerWedgeTexCoord ( _mesh ) )
return ;
cmap . clear ( ) ;
typename MESHTYPE : : FaceIterator infrange = _mesh . face . begin ( ) ;
short texind = std : : numeric_limits < short > : : max ( ) ;
int hh = 0 ;
for ( typename MESHTYPE : : FaceIterator fit = _mesh . face . begin ( ) ; fit ! = _mesh . face . end ( ) ; + + fit )
{
if ( fit - > WT ( 0 ) . N ( ) ! = texind )
{
if ( ( texind ! = std : : numeric_limits < short > : : max ( ) ) | | ( fit = = _mesh . face . end ( ) - 1 ) )
{
GLuint lowind = std : : distance ( _mesh . face . begin ( ) , infrange ) ;
GLuint topind = std : : distance ( _mesh . face . begin ( ) , fit ) - 1 ;
cmap [ texind ] . push_back ( std : : make_pair ( lowind , topind ) ) ;
infrange = fit ;
}
texind = fit - > WT ( 0 ) . N ( ) ;
}
+ + hh ;
}
cmap [ texind ] . push_back ( std : : make_pair ( std : : distance ( _mesh . face . begin ( ) , infrange ) , std : : distance ( _mesh . face . begin ( ) , _mesh . face . end ( ) - 1 ) ) ) ;
}
//ideally this should be const. I'm not yet sure if VCGLib will allow me to declare it as constant
MESHTYPE & _mesh ;
MemoryInfo & _gpumeminfo ;
std : : vector < GLBufferObject * > _bo ;
2015-06-10 20:13:28 +02:00
//GLuint vaohandle;
2015-06-14 11:39:42 +02:00
2015-06-04 02:18:35 +02:00
std : : vector < std : : pair < short , GLuint > > _texindnumtriangles ;
bool _lastfeedingusedreplicatedpipeline ;
bool _borendering ;
size_t _perbatchsimplex ;
ChunkMap _chunkmap ;
} ;
}
# endif