gl_mesh_attributes_feeder.h
Go to the documentation of this file.
00001 /****************************************************************************
00002 * VCGLib                                                            o o     *
00003 * Visual and Computer Graphics Library                            o     o   *
00004 *                                                                _   O  _   *
00005 * Copyright(C) 2004                                                \/)\/    *
00006 * Visual Computing Lab                                            /\/|      *
00007 * ISTI - Italian National Research Council                           |      *
00008 *                                                                    \      *
00009 * All rights reserved.                                                      *
00010 *                                                                           *
00011 * This program is free software; you can redistribute it and/or modify      *
00012 * it under the terms of the GNU General Public License as published by      *
00013 * the Free Software Foundation; either version 2 of the License, or         *
00014 * (at your option) any later version.                                       *
00015 *                                                                           *
00016 * This program is distributed in the hope that it will be useful,           *
00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of            *
00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
00019 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt)          *
00020 * for more details.                                                         *
00021 *                                                                           *
00022 ****************************************************************************/
00023 
00024 #ifndef __VCG_GL_MESH_ATTRIBUTES_FEEDER
00025 #define __VCG_GL_MESH_ATTRIBUTES_FEEDER
00026 
00027 #include <queue>
00028 #include <vector>
00029 #include <map>
00030 #include <algorithm>
00031 #include <stdexcept>
00032 #include <limits>
00033 
00034 //#include <GL/glew.h>
00035 #include <wrap/gl/space.h>
00036 #include <wrap/gl/math.h>
00037 #include <vcg/space/color4.h>
00038 #include<wrap/system/memory_info.h>
00039 
00040 
00041 namespace vcg
00042 {
00043     struct GLFeederInfo
00044     {
00045         struct GLFeederException : public std::exception
00046         {
00047             GLFeederException(const char* text)
00048                 :std::exception(),_text(text) {}
00049 
00050             ~GLFeederException() throw() {}
00051             inline const char* what() const throw() {return _text.c_str();}
00052         private:
00053             std::string _text;
00054         };
00055 
00056         enum ATT_NAMES
00057         {
00058             ATT_ALL = -1,
00059             ATT_VERTPOSITION = 0,
00060             ATT_VERTNORMAL = 1,
00061             ATT_FACENORMAL = 2,
00062             ATT_VERTCOLOR = 3,
00063             ATT_FACECOLOR = 4,
00064             ATT_MESHCOLOR = 5,
00065             ATT_VERTTEXTURE = 6,
00066             ATT_WEDGETEXTURE = 7,
00067             ATT_VERTINDEX = 8,
00068             ATT_NAMES_ARITY = 9
00069         };
00070 
00071         enum PRIMITIVE_MODALITY
00072         {
00073             PR_NONE = 0,
00074             PR_POINTS = 1,
00075             PR_TRIANGLES = 2,
00076             PR_QUADS = 3,
00077             PR_NAMES_ARITY = 4
00078         };
00079 
00080         typedef unsigned int ATT_BIT_MASK;
00081 
00082         static ATT_BIT_MASK attBitMask(ATT_NAMES attname)
00083         {
00084             if ((attname == ATT_ALL) || (attname == ATT_VERTINDEX))
00085                 return 0xffffffff;
00086 
00087             if ((attname >= ATT_VERTPOSITION) && (attname <= ATT_WEDGETEXTURE))
00088             {
00089                 static const ATT_BIT_MASK res[] = {
00090                     0x00000000, /*attVertPosition()*/
00091                     0x00000001, /*attVertNormal()*/
00092                     0x00000002, /*attFaceNormal()*/
00093                     0x00000004, /*attVertColor()*/
00094                     0x00000008, /*attFaceColor()*/
00095                     0x00000010, /*attVertTexture()*/
00096                     0x00000020}; /*attWedgeTexture()*/
00097                     return res[attname];
00098             }
00099             else
00100                 throw GLFeederException("Out of range value\n");
00101             return 0;
00102         }
00103 
00104         class ReqAtts
00105         {
00106         public:
00107             ReqAtts()
00108             {
00109                 reset();
00110             }
00111 
00112 
00113             const bool& operator[](ATT_NAMES att) const
00114             {
00115                 size_t ii = static_cast<size_t>(att);
00116                 if (ii > ATT_VERTINDEX)
00117                     throw GLFeederException("Out of range value\n");
00118                 return _atts[ii];
00119             }
00120 
00121             bool& operator[](ATT_NAMES att)
00122             {
00123                 size_t ii = static_cast<size_t>(att);
00124                 if (ii > ATT_VERTINDEX)
00125                     throw GLFeederException("Out of range value\n");
00126                 return _atts[ii];
00127             }
00128 
00129             virtual void reset()
00130             {
00131                 for(size_t ii = 0;ii < _attssize;++ii)
00132                     _atts[ii] = false;
00133                 _pm = PR_NONE;
00134             }
00135 
00136             inline PRIMITIVE_MODALITY& primitiveModality()
00137             {
00138                 return _pm;
00139             }
00140 
00141             inline PRIMITIVE_MODALITY primitiveModality() const
00142             {
00143                 return _pm;
00144             }
00145 
00146             inline static size_t possibleAttributesNumber()
00147             {
00148                 return _attssize;
00149             }
00150 
00151             static ReqAtts setUnion(const ReqAtts& a,const ReqAtts& b)
00152             {
00153                 ReqAtts res;
00154                 for(size_t ii = 0; ii < ReqAtts::possibleAttributesNumber();++ii)
00155                 {
00156                     ATT_NAMES name = static_cast<ATT_NAMES>(ii);
00157                     res[name] = a[name] || b[name];
00158                 }
00159 
00160                 res.primitiveModality() = a.primitiveModality();
00161                 if ((unsigned int) res.primitiveModality() <= (unsigned int) b.primitiveModality())
00162                     res.primitiveModality() = b.primitiveModality();
00163                 return res;
00164             }
00165 
00166             static ReqAtts setComplement(const ReqAtts& a,const ReqAtts& b)
00167             {
00168                 /*TRUTH TABLE*/
00169                 //this[ATT_NAMES] | rq[ATT_NAMES] | res
00170                 //    true        |     true      | false
00171                 //    true        |     false     | true
00172                 //    false       |     true      | false
00173                 //    false       |     false     | false
00174 
00175                 ReqAtts res = a;
00176                 for(size_t ii = 0; ii < ReqAtts::possibleAttributesNumber();++ii)
00177                 {
00178                     ATT_NAMES name = static_cast<ATT_NAMES>(ii);
00179                     if (res[name])
00180                         res[name] = !(b[name]);
00181                 }
00182 
00183                 res.primitiveModality() = b.primitiveModality();
00184                 return res;
00185             }
00186 
00187             static bool isReplicatedPipeline(const ReqAtts& rqatt)
00188             {
00189                 return (rqatt[ATT_FACENORMAL] || rqatt[ATT_FACECOLOR] || rqatt[ATT_WEDGETEXTURE]);
00190             }
00191 
00192             static bool isVertexIndexingRequired(const ReqAtts& rqatt)
00193             {
00194                 PRIMITIVE_MODALITY pm = rqatt.primitiveModality();
00195                 return (!isReplicatedPipeline(rqatt) && (pm != PR_POINTS) && (pm != PR_NONE));
00196             }
00197 
00198             template<typename MESHTYPE>
00199             static void computeARequestedAttributesSetCompatibleWithMesh(ReqAtts& rqatt,const MESHTYPE& mesh)
00200             {
00201                 if (mesh.VN() == 0)
00202                 {
00203                     rqatt.reset();
00204                     return;
00205                 }
00206 
00207                 rqatt[ATT_VERTPOSITION] = true;
00208                 rqatt[ATT_VERTNORMAL] = rqatt[ATT_VERTNORMAL] && vcg::tri::HasPerVertexNormal(mesh);
00209                 rqatt[ATT_FACENORMAL] = rqatt[ATT_FACENORMAL] && vcg::tri::HasPerFaceNormal(mesh);
00210                 rqatt[ATT_VERTCOLOR] = rqatt[ATT_VERTCOLOR] && vcg::tri::HasPerVertexColor(mesh);
00211                 rqatt[ATT_FACECOLOR] = rqatt[ATT_FACECOLOR] && vcg::tri::HasPerFaceColor(mesh);
00212                 rqatt[ATT_MESHCOLOR] = rqatt[ATT_MESHCOLOR];
00213                 rqatt[ATT_VERTTEXTURE] = rqatt[ATT_VERTTEXTURE] && vcg::tri::HasPerVertexTexCoord(mesh);
00214                 rqatt[ATT_WEDGETEXTURE] = rqatt[ATT_WEDGETEXTURE] && vcg::tri::HasPerWedgeTexCoord(mesh);
00215                 rqatt[ATT_VERTINDEX] = isVertexIndexingRequired(rqatt);
00216             }
00217 
00218         protected:
00219             static const size_t _attssize = ATT_NAMES_ARITY;
00220             bool _atts[_attssize];
00221             PRIMITIVE_MODALITY _pm;
00222         };
00223     };
00224 
00225     //WARNING! member functions of this class should be called by the host application using concurrency
00226     template <typename MESHTYPE>
00227     class GLMeshAttributesFeeder : public GLFeederInfo
00228     {
00229     public:
00230         GLMeshAttributesFeeder(/*const*/ MESHTYPE& mesh,MemoryInfo& meminfo, size_t perbatchprimitives)
00231             :_mesh(mesh),_gpumeminfo(meminfo),_bo(ATT_NAMES_ARITY,NULL),_currallocatedboatt(),_lastfeedingusedreplicatedpipeline(false),_perbatchprim(perbatchprimitives),_chunkmap(),_borendering(false),_rendermodinitialized(false)
00232         {
00233             _bo[GLFeederInfo::ATT_VERTPOSITION] = new GLBufferObject(3,GL_FLOAT,GL_VERTEX_ARRAY,GL_ARRAY_BUFFER);
00234             _bo[GLFeederInfo::ATT_VERTNORMAL] = new GLBufferObject(3,GL_FLOAT,GL_NORMAL_ARRAY,GL_ARRAY_BUFFER);
00235             _bo[GLFeederInfo::ATT_FACENORMAL] = new GLBufferObject(3,GL_FLOAT,GL_NORMAL_ARRAY,GL_ARRAY_BUFFER);
00236             _bo[GLFeederInfo::ATT_VERTCOLOR] = new GLBufferObject(4,GL_UNSIGNED_BYTE,GL_COLOR_ARRAY,GL_ARRAY_BUFFER);
00237             _bo[GLFeederInfo::ATT_FACECOLOR] = new GLBufferObject(4,GL_UNSIGNED_BYTE,GL_COLOR_ARRAY,GL_ARRAY_BUFFER);
00238             /*MESHCOLOR has not a buffer object associated with it. It's just a call to glColor3f. it's anyway added to the _bo arrays for sake of coherence*/
00239             _bo[GLFeederInfo::ATT_MESHCOLOR] = NULL;
00240             _bo[GLFeederInfo::ATT_VERTTEXTURE] = new GLBufferObject(2,GL_FLOAT,GL_TEXTURE_COORD_ARRAY,GL_ARRAY_BUFFER);
00241             _bo[GLFeederInfo::ATT_WEDGETEXTURE] = new GLBufferObject(2,GL_FLOAT,GL_TEXTURE_COORD_ARRAY,GL_ARRAY_BUFFER);
00242             _bo[GLFeederInfo::ATT_VERTINDEX] = new GLBufferObject(3,GL_UNSIGNED_INT,GL_ELEMENT_ARRAY_BUFFER);
00243         }
00244 
00245         ~GLMeshAttributesFeeder()
00246         {
00247             for(size_t ii = 0;ii < _bo.size();++ii)
00248                 delete _bo[ii];
00249             _bo.clear();
00250         }
00251 
00252         //void meshAttributesUpdated(int mask)
00253         //{
00254         //    if ((_mesh.VN() != _mesh.vert.size()) || (_mesh.FN() != _mesh.face.size()))
00255         //    {
00256         //        throw GLFeederException("The current mesh contains vertices/faces marked as deleted!\nPlease, call the compact vectors function in order to properly remove them\n");
00257         //        return;
00258         //    }
00259 
00260         //    if (!_rendermodinitialized)
00261         //    {
00262         //        throw GLFeederException("Required attributes for rendering were not properly initialized\nInvokation of setAttributesToBeRendered function is strictly required!\n");
00263         //        return;
00264         //    }
00265 
00266         //    bool boupdatedrequired = false;
00267         //    if (((mask & attBitMask(GLFeederInfo::ATT_VERTPOSITION)) || (mask & attBitMask(ATT_ALL))) && (_currallocatedboatt[ATT_VERTPOSITION]))
00268         //    {
00269         //        boupdatedrequired = true;
00270         //        _bo[GLFeederInfo::ATT_VERTPOSITION]->_isvalid = false;
00271         //    }
00272 
00273         //    if (((mask & attBitMask(GLFeederInfo::ATT_VERTNORMAL)) || (mask & attBitMask(ATT_ALL))) &&  (_currallocatedboatt[ATT_VERTNORMAL] && vcg::tri::HasPerVertexNormal(_mesh)))
00274         //    {
00275         //        boupdatedrequired = true;
00276         //        _bo[GLFeederInfo::ATT_VERTNORMAL]->_isvalid = false;
00277         //    }
00278 
00279         //    if (((mask & attBitMask(GLFeederInfo::ATT_FACENORMAL)) || (mask & attBitMask(ATT_ALL))) && (_currallocatedboatt[ATT_FACENORMAL] && vcg::tri::HasPerFaceNormal(_mesh)))
00280         //    {
00281         //        boupdatedrequired = true;
00282         //        _bo[GLFeederInfo::ATT_FACENORMAL]->_isvalid = false;
00283         //    }
00284 
00285         //    if (((mask & attBitMask(GLFeederInfo::ATT_VERTCOLOR)) || (mask & attBitMask(ATT_ALL))) && (_currallocatedboatt[ATT_VERTCOLOR] && vcg::tri::HasPerVertexColor(_mesh)))
00286         //    {
00287         //        boupdatedrequired = true;
00288         //        _bo[GLFeederInfo::ATT_VERTCOLOR]->_isvalid = false;
00289         //    }
00290 
00291         //    if (((mask & attBitMask(GLFeederInfo::ATT_FACECOLOR)) || (mask & attBitMask(ATT_ALL))) && (_currallocatedboatt[ATT_FACECOLOR] && vcg::tri::HasPerFaceColor(_mesh)))
00292         //    {
00293         //        boupdatedrequired = true;
00294         //        _bo[GLFeederInfo::ATT_FACECOLOR]->_isvalid = false;
00295         //    }
00296 
00297 
00298         //    if (((mask & attBitMask(GLFeederInfo::ATT_VERTTEXTURE)) || (mask & attBitMask(ATT_ALL))) && (_currallocatedboatt[ATT_VERTTEXTURE] && vcg::tri::HasPerVertexTexCoord(_mesh)))
00299         //    {
00300         //        boupdatedrequired = true;
00301         //        _bo[GLFeederInfo::ATT_VERTTEXTURE]->_isvalid = false;
00302         //    }
00303 
00304         //    if (((mask & attBitMask(GLFeederInfo::ATT_WEDGETEXTURE)) || (mask & attBitMask(ATT_ALL))) && (_currallocatedboatt[ATT_WEDGETEXTURE] && vcg::tri::HasPerWedgeTexCoord(_mesh)))
00305         //    {
00306         //        boupdatedrequired = true;
00307         //        _bo[GLFeederInfo::ATT_WEDGETEXTURE]->_isvalid = false;
00308         //    }
00309 
00310         //    if (mask & attBitMask(ATT_ALL))
00311         //    {
00312         //        boupdatedrequired = true;
00313         //        _bo[GLFeederInfo::ATT_VERTINDEX]->_isvalid = false;
00314         //    }
00315 
00316         //    if (boupdatedrequired)
00317         //        tryToAllocateAndCopyAttributesInBO();
00318         //}
00319 
00320         ReqAtts setupRequestedAttributes(const ReqAtts& rq,bool& allocated)
00321         {
00322 
00323             if (!_rendermodinitialized)
00324                 _rendermodinitialized = true;
00325 
00326             try
00327             {
00328                 ReqAtts tmp = rq;
00329                 ReqAtts::computeARequestedAttributesSetCompatibleWithMesh(tmp,_mesh);
00330                 tmp = ReqAtts::setUnion(_currallocatedboatt,tmp);
00331                
00332                 allocated = tryToAllocateAndCopyAttributesInBO(tmp);
00333                 return tmp;
00334             }
00335             catch (GLFeederException& e)
00336             {
00337                 return ReqAtts();
00338             }
00339             return ReqAtts();
00340         }
00341 
00342         ReqAtts removeRequestedAttributes(const ReqAtts& rq)
00343         {
00344             return _currallocatedboatt = ReqAtts::setComplement(rq,_currallocatedboatt);
00345         }
00346 
00347         void invalidateRequestedAttributes(const ReqAtts& rq)
00348         {
00349             size_t ii = 0;
00350             for(typename std::vector<GLBufferObject*>::iterator it = _bo.begin();it != _bo.end();++it)
00351             {
00352                 ATT_NAMES boname = static_cast<ATT_NAMES>(ii);
00353                 if ((*it != NULL) && (rq[boname]))
00354                     (*it)->_isvalid = false;
00355                 ++ii;
00356             }
00357         }
00358 
00359         void buffersDeAllocationRequested()
00360         {
00361             size_t ii = 0;
00362             for(typename std::vector<GLBufferObject*>::iterator it = _bo.begin();it != _bo.end();++it)
00363             {
00364                 ATT_NAMES boname = static_cast<ATT_NAMES>(ii);
00365                 if (*it != NULL)
00366                     bufferDeAllocationRequested(boname);
00367                 ++ii;
00368             }
00369         }
00370 
00371         void buffersDeAllocationRequested(const ReqAtts& rq)
00372         {
00373             size_t ii = 0;
00374             for(typename std::vector<GLBufferObject*>::iterator it = _bo.begin();it != _bo.end();++it)
00375             {
00376                 ATT_NAMES boname = static_cast<ATT_NAMES>(ii);
00377                 if ((*it != NULL) && (rq[boname]))
00378                     bufferDeAllocationRequested(boname);
00379                 ++ii;
00380             }
00381         }
00382 
00383         void draw(const ReqAtts& rq,const std::vector<GLuint> textid = std::vector<GLuint>())
00384         {
00385 
00386             if (isPossibleToUseBORendering())
00387             {
00388                 switch(rq.primitiveModality())
00389                 {
00390                 case(PR_TRIANGLES):
00391                     drawTriangles(rq,textid);
00392                     break;
00393                 case(PR_POINTS):
00394                     drawPoints(rq);
00395                     break;
00396                 case (PR_QUADS):
00397                     break;
00398                 default:
00399                     break;
00400                 }
00401             }
00402             else
00403                 immediateModeRendering(rq,textid);
00404         }
00405 
00406         void setPerBatchPrimitives(size_t perbatchprimitives)
00407         {
00408             _perbatchprim = perbatchprimitives;
00409         }
00410 
00411         size_t perBatchPrimitives() const
00412         {
00413             return _perbatchprim;
00414         }
00415 
00416         bool isPossibleToUseBORendering() const
00417         {
00418             return _borendering;
00419         }
00420 
00421  
00422 
00423         //void invalidateRequestedAttributes(ReqAtts& rq)
00424         //{
00425         //    size_t ii = 0;
00426         //    for(typename std::vector<GLBufferObject*>::iterator it = _bo.begin();it != _bo.end();++it)
00427         //    {
00428         //        ATT_NAMES boname = static_cast<ATT_NAMES>(ii);
00429         //        if (((*it) != NULL) && (rq[boname]))
00430         //            (*it)->_isvalid = false;
00431         //        ++ii;
00432         //    }
00433         //    //_currallocatedboatt = vcg::GLFeederInfo::ReqAtts::setComplement(_currallocatedboatt,rq);
00434         //}
00435 
00436     protected:
00437         struct GLBufferObject
00438         {
00439             GLBufferObject(size_t components,GLenum gltype,GLenum clientstatetag,GLenum target)
00440                 :_size(0),_components(components),_isvalid(false),_gltype(gltype),_clientstatetag(clientstatetag),_target(target),_bohandle(0)
00441             {
00442             }
00443 
00444             GLBufferObject(size_t components,GLenum gltype,GLenum target)
00445                 :_size(0),_components(components),_isvalid(false),_gltype(gltype),_clientstatetag(),_target(target),_bohandle(0)
00446             {
00447             }
00448 
00449             size_t getSizeOfGLType() const
00450             {
00451                 switch(_gltype)
00452                 {
00453                 case(GL_FLOAT):
00454                     return sizeof(GLfloat);
00455                 case(GL_INT):
00456                     return sizeof(GLint);
00457                 case(GL_UNSIGNED_INT):
00458                     return sizeof(GLuint);
00459                 case(GL_UNSIGNED_BYTE):
00460                     return sizeof(GLubyte);
00461                 }
00462                 return 0;
00463             }
00464 
00465             size_t _size;
00466             const size_t _components;
00467             bool _isvalid;
00468             const GLenum _gltype;
00469             const GLenum _target;
00470 
00471             /*WARNING!!!!!!!!!!!!!!!!! In openGL INDEX BO doesn't require to be enabled/disabled so has NOT a valid tag associated.
00472             In this case the client state tag remains not initialized and it's not meaningful */
00473             const GLenum _clientstatetag;
00474             /**********************************************************************************/
00475 
00476             GLuint _bohandle;
00477         };
00478 
00479         const GLBufferObject& getBufferObjectInfo(ATT_NAMES boname) const
00480         {
00481             return _bo[boname];
00482         }
00483 
00484         void bufferDeAllocationRequested(const ATT_NAMES att)
00485         {
00486             size_t ind = static_cast<size_t>(att);
00487             if ((ind < 0) || (ind >= _bo.size()))
00488                 return;
00489             GLBufferObject* bobj = _bo[att];
00490             if (bobj == NULL)
00491                 return;
00492            
00493             if ((att != ATT_VERTINDEX ) && (ATT_MESHCOLOR))
00494                 glDisableClientState(bobj->_clientstatetag);
00495 
00496             glDeleteBuffers(1,&(bobj->_bohandle));
00497             bobj->_bohandle = 0;
00498             if (bobj->_size > 0)
00499                 //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
00500                 _gpumeminfo.releasedMemory(bobj->_size * bobj->getSizeOfGLType());
00501             bobj->_isvalid = false;
00502             bobj->_size = 0;
00503             _currallocatedboatt[att] = false; 
00504         }
00505 
00506         bool buffersAllocationFunction(const ReqAtts& req,std::vector<bool>& attributestobeupdated)
00507         {
00508             bool replicated = ReqAtts::isReplicatedPipeline(req);
00509             attributestobeupdated.clear();
00510             attributestobeupdated.resize(_bo.size());
00511             std::ptrdiff_t bomemoryrequiredbymesh = bufferObjectsMemoryRequired(req);
00512             bool generateindex = ReqAtts::isVertexIndexingRequired(req);
00513             unsigned int ii = 0;
00514             for(typename std::vector<GLBufferObject*>::iterator it = _bo.begin();it != _bo.end();++it)
00515             {
00516                 ATT_NAMES boname = static_cast<ATT_NAMES>(ii);
00517                 size_t sz = boExpectedSize(boname,replicated,generateindex);
00518                 size_t dim = boExpectedDimension(boname,replicated,generateindex);
00519 
00520                 if (((*it) != NULL) && (
00521                     /*a mesh attributes has been updated and the number of already allocated bo cells to contain the attribute values doesn't suit anymore
00522                     (i.e. if i change just the vertex positions without changing the vertex numbers i have not to reallocate the previous vertposition bo, it's just sufficient to update the vertex coordinates)*/
00523                     ((!(*it)->_isvalid) && (sz != (*it)->_size)) ||
00524                     /*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*/
00525                     (replicated && !_lastfeedingusedreplicatedpipeline && (isPerVertexAttribute(boname) || (boname == GLFeederInfo::ATT_VERTINDEX))) ||
00526                     /*we switched back from the replicated pipeline to the indexed one. All the bos have to be regenerated*/
00527                     (!replicated && _lastfeedingusedreplicatedpipeline) ||
00528                     /*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*/
00529                     (((*it)->_isvalid) && (sz != (*it)->_size))
00530                     //||
00531                     //the buffer is valid, but the attribute is not required to be displayed
00532                     /*(((*it)->_isvalid) && !isAttributeRequiredToBeDisplayed(boname)))*/
00533                     ))
00534                 {
00535                     bufferDeAllocationRequested(boname); 
00536                 }
00537                 /*there are already mesh attributes properly allocated in memory, we don't need to allocate them again. there could be invalid values attributes but with properly memory space already allocated in memory
00538                 (i.e. i changed the pervertex colors but the vertex numbers remained constant)*/
00539                 if ((*it != NULL) && (/*((*it)->_isvalid) &&*/ (sz == (*it)->_size)))
00540                     bomemoryrequiredbymesh -= dim;
00541                 ++ii;
00542             }
00543 
00544             if (!_gpumeminfo.isAdditionalMemoryAvailable(bomemoryrequiredbymesh))
00545             {
00546                 std::cout << "no additional memory available!!! memory required: " << bomemoryrequiredbymesh << std::endl;
00547                 ii = 0;
00548                 for(typename std::vector<GLBufferObject*>::iterator it = _bo.begin();it != _bo.end();++it)
00549                 {
00550                     ATT_NAMES boname = static_cast<ATT_NAMES>(ii);
00551                     size_t sz(boExpectedSize(boname,replicated,generateindex));
00552                     //there are already valid mesh attributes properly allocated in memory but there is not enough gpu memory for the remaining mesh.
00553                     //we have to deallocate the previously allocated mesh attributes
00554                     if ((*it != NULL) && ((sz == (*it)->_size)))
00555                     {
00557                         //std::ptrdiff_t dim(boExpectedDimension(boname,replicated,generateindex));
00559                         //if ((*it)->_size > 0)
00560                         //{
00561 
00562 
00563                         //    /*WARNING! THIS CODE MUST BE INCAPSULATED INTO A DEALLOCATE FUNCTION IN A PROPER MADE BUFFER OBJECT CLASS
00564                         //    I DON'T INSERT IT INTO THE GLBufferObjectInfo CLASS CAUSE I CONSIDER IT A TEMPORARY PRIVATE STRUCT*/
00565                         //    glDeleteBuffers(1,&(*it)->_bohandle);
00566                         //    (*it)->_bohandle = 0;
00567                         //    _gpumeminfo.releasedMemory(dim);
00568                         //}
00569                         //(*it)->_isvalid = false;
00570                         //(*it)->_size = 0;
00572                         //_currallocatedboatt[boname] = false; 
00573                         bufferDeAllocationRequested(boname); 
00574                     }
00575                     ++ii;
00576                 }
00577                 _borendering = false;
00578                 _lastfeedingusedreplicatedpipeline = false;
00579                 return false;
00580             }
00581             else
00582             {
00583 
00584                 //I have to update the invalid buffers requested to be imported
00585                 for(size_t kk = 0;kk < attributestobeupdated.size();++kk)
00586                     attributestobeupdated[kk] = req[static_cast<ATT_NAMES>(kk)];
00587                 bool failedallocation = false;
00588                 size_t ii = 0;
00589                 typename std::vector<GLBufferObject*>::iterator it = _bo.begin();
00590                 while((it != _bo.end()) && (!failedallocation))
00591                 {
00592                     ATT_NAMES boname = static_cast<ATT_NAMES>(ii);
00593                     GLBufferObject* cbo = _bo.at(boname);
00594                     bool importatt = req[boname];
00595                     //glBindVertexArray(vaohandlespecificperopenglcontext);
00596 
00597                     /*if a bo is not valid but at this point has a valid handle means that attribute values have been updated but the arity of the vertices/faces didn't change. i can use the already allocated space*/
00598                     bool notvalidandtoberegenerated = (cbo != NULL) && (!cbo->_isvalid) && (cbo->_bohandle == 0) && (importatt);
00599                     if (notvalidandtoberegenerated)
00600                     {
00601                         cbo->_size = boExpectedSize(boname,replicated,generateindex);
00602                         std::ptrdiff_t dim = boExpectedDimension(boname,replicated,generateindex);
00603                         
00604                         glGenBuffers(1, &cbo->_bohandle);
00605                         glBindBuffer(cbo->_target, cbo->_bohandle);
00606                         //we call glGetError BEFORE the glBufferData function in order to clean the error flag
00607                         GLenum err = glGetError();
00608                         glBufferData(cbo->_target, dim, NULL, GL_STATIC_DRAW);
00609                         err = glGetError();
00610                         //even if there according the MemoryInfo subclass there is enough space we were not able to allocate an attribute buffer object. We have to deallocate all the bos related to this mesh
00611                         failedallocation = (err == GL_OUT_OF_MEMORY);
00612                         if (!failedallocation)
00613                         {
00614                             //setBufferPointerEnableClientState(boname);
00615                             setBufferPointer(boname);
00616                             _gpumeminfo.acquiredMemory(dim);
00617                         }
00618                         attributestobeupdated[boname] = !failedallocation;
00619                         cbo->_isvalid = !failedallocation;
00620                         _borendering = !failedallocation;
00621                         glBindBuffer(cbo->_target, 0);
00622                         _currallocatedboatt[boname] = !failedallocation;
00623                     }
00624                     else
00625                     {
00626                         attributestobeupdated[boname] = false;
00627                         //values in the bo have to be updated but the arity of the attribute doesn't change. i can use the already allocated space without reallocating it
00628                         if ((cbo != NULL) && (!cbo->_isvalid) && (cbo->_bohandle != 0) && (importatt))
00629                         {
00630                             attributestobeupdated[boname] = true;
00631                             cbo->_isvalid = true;
00632                             _currallocatedboatt[boname] = true;
00633                         }
00634                         if ((cbo != NULL) && (!importatt))
00635                         {
00636                             cbo->_isvalid = false;
00637                             _currallocatedboatt[boname] = false;
00638                         }
00639                     }
00640 
00641                     //if ((cbo == NULL) || (!cbo->_isvalid))
00642                     //{
00643                     //  //glBindVertexArray(_vaohandle);
00644                     //  disableClientState(boname,requestedattributes);
00645                     //  //glBindVertexArray(0);
00646                     //}
00647                     ++it;
00648                     ++ii;
00649                     //glBindVertexArray(0);
00650                 }
00651                 if (failedallocation)
00652                    buffersDeAllocationRequested();
00653                 _borendering = !failedallocation;
00654                 _lastfeedingusedreplicatedpipeline = replicated;
00655                 return _borendering;
00656             }
00657         }
00658 
00659         bool tryToAllocateAndCopyAttributesInBO(const ReqAtts& req)
00660         {
00661             std::vector<bool> attributestobeupdated;
00662             bool immediatemode = !(buffersAllocationFunction(req,attributestobeupdated));
00663             bool replicated = ReqAtts::isReplicatedPipeline(req);
00664 
00665             if (immediatemode)
00666                 return false;
00667 
00668             bool somethingtoupdate = false;
00669             for(size_t hh = 0;hh < attributestobeupdated.size();++hh)
00670                 somethingtoupdate = somethingtoupdate || attributestobeupdated[hh];
00671             if (somethingtoupdate)
00672             {
00673                 if (replicated)
00674                 {
00675                     //WARNING!In case we have to update the wedgetexture bo maybe (not always!) we must update also the other buffer already in memory
00676                     //cause the wedgetexture pipeline force a change in the order of the triangles in GPU.
00677                     //they are now ordered by the texture seam and not more by the triangle index!
00678                     if (attributestobeupdated[ATT_WEDGETEXTURE])
00679                     {
00680                         for(size_t jj = 0;jj < attributestobeupdated.size();++jj)
00681                         {
00682                             ATT_NAMES att = static_cast<ATT_NAMES>(jj);
00683                             attributestobeupdated[jj] = _currallocatedboatt[att] || attributestobeupdated[jj];
00684                         }
00685                     }
00686                     updateBuffersReplicatedPipeline(attributestobeupdated);
00687                 }
00688                 else
00689                     updateBuffersIndexedPipeline(attributestobeupdated);
00690                 glFinish();
00691             }
00692             return true;
00693         }
00694 
00695         //bool tryToAllocateAttributesInBO(NORMAL_MODALITY nm,COLOR_MODALITY cm)
00696         //{
00697         //      std::vector<bool> importattribute(_bo.size());
00698         //      std::vector<bool> attributestobeupdated;
00699         //      attributesToBeImportedInPointBasedPipeline(importattribute, nm, cm);
00700         //      bool immediatemode = !(buffersAllocationFunction(nm,cm,TX_NONE,importattribute,attributestobeupdated));
00701         //      if (immediatemode)
00702         //              return false;
00703         //
00704         //      bool somethingtoupdate = false;
00705         //      for(size_t hh = 0;hh < attributestobeupdated.size();++hh)
00706         //              somethingtoupdate = somethingtoupdate || attributestobeupdated[hh];
00707         //      if (somethingtoupdate)
00708         //              updateBuffersIndexedPipeline(attributestobeupdated);
00709         //      return true;
00710         //}
00711 
00712         bool updateBuffersIndexedPipeline(const std::vector<bool>& attributestobeupdated)
00713         {
00714             _chunkmap.clear();
00715             size_t vn = _mesh.VN();
00716             size_t tn = _mesh.FN();
00717 
00718             size_t facechunk = std::min(size_t(tn),_perbatchprim);
00719             size_t vertexchunk = std::min(size_t(vn),_perbatchprim);
00720 
00721             std::vector<vcg::Point3f> pv; //position vector
00722             if (attributestobeupdated[GLFeederInfo::ATT_VERTPOSITION])
00723                 pv.resize(vertexchunk);
00724 
00725             std::vector<vcg::Point3f> nv; //per vertex normal vector
00726             if (attributestobeupdated[GLFeederInfo::ATT_VERTNORMAL])
00727                 nv.resize(vertexchunk);
00728 
00729             std::vector<vcg::Color4b> cv; // Per vertex color vector
00730             if (attributestobeupdated[GLFeederInfo::ATT_VERTCOLOR])
00731                 cv.resize(vertexchunk);
00732 
00733             std::vector<float> tv; // per vertex texture coord vector
00734             if (attributestobeupdated[GLFeederInfo::ATT_VERTTEXTURE])
00735                 tv.resize(vertexchunk * 2);
00736 
00737             size_t chunkingpu = 0;
00738 
00739             for(size_t i=0;i<vn;++i)
00740             {
00741                 size_t chunkindex = i % vertexchunk;
00742                 if (attributestobeupdated[GLFeederInfo::ATT_VERTPOSITION])
00743                     pv[chunkindex].Import(_mesh.vert[i].cP());
00744 
00745                 if (attributestobeupdated[GLFeederInfo::ATT_VERTNORMAL])
00746                 {
00747                     nv[chunkindex].Import(_mesh.vert[i].cN());
00748                     nv[chunkindex].Normalize();
00749                 }
00750 
00751                 if (attributestobeupdated[GLFeederInfo::ATT_VERTCOLOR])
00752                     cv[chunkindex] = _mesh.vert[i].cC();
00753                 if (attributestobeupdated[GLFeederInfo::ATT_VERTTEXTURE])
00754                 {
00755                     tv[chunkindex*2+0] = _mesh.vert[i].cT().U();
00756                     tv[chunkindex*2+1] = _mesh.vert[i].cT().V();
00757                 }
00758 
00759                 if((i == vn - 1) || (chunkindex == vertexchunk - 1))
00760                 {
00761                     size_t chunksize = vertexchunk;
00762                     if (i == vn - 1)
00763                         chunksize = chunkindex + 1;
00764 
00765                     if (attributestobeupdated[GLFeederInfo::ATT_VERTPOSITION])
00766                     {
00767                         GLBufferObject* buffobj = _bo[GLFeederInfo::ATT_VERTPOSITION];
00768                         glBindBuffer(GL_ARRAY_BUFFER, buffobj->_bohandle);
00769                         glBufferSubData(GL_ARRAY_BUFFER,chunkingpu * vertexchunk * buffobj->_components * buffobj->getSizeOfGLType(),buffobj->_components * buffobj->getSizeOfGLType() * chunksize,&pv[0]);
00770                         //std::vector<vcg::Point3f> tmppv; //position vector
00771                         //if (attributestobeupdated[GLFeederInfo::ATT_VERTPOSITION])
00772                         //    tmppv.resize(vertexchunk);
00773                         //glGetBufferSubData(GL_ARRAY_BUFFER,0,buffobj->_components * buffobj->getSizeOfGLType() * chunksize,&tmppv[0]);
00774                         glBindBuffer(GL_ARRAY_BUFFER, 0);
00775                       
00776                     }
00777                     if (attributestobeupdated[GLFeederInfo::ATT_VERTNORMAL])
00778                     {
00779                         GLBufferObject* buffobj = _bo[GLFeederInfo::ATT_VERTNORMAL];
00780                         glBindBuffer(GL_ARRAY_BUFFER, buffobj->_bohandle);
00781                         glBufferSubData(GL_ARRAY_BUFFER,chunkingpu * vertexchunk * buffobj->_components * buffobj->getSizeOfGLType(),buffobj->_components * buffobj->getSizeOfGLType() * chunksize,&nv[0]);
00782                         glBindBuffer(GL_ARRAY_BUFFER, 0);
00783                     }
00784                     if (attributestobeupdated[GLFeederInfo::ATT_VERTCOLOR])
00785                     {
00786                         GLBufferObject* buffobj = _bo[GLFeederInfo::ATT_VERTCOLOR];
00787                         glBindBuffer(GL_ARRAY_BUFFER, buffobj->_bohandle);
00788                         glBufferSubData(GL_ARRAY_BUFFER,chunkingpu * vertexchunk * buffobj->_components * buffobj->getSizeOfGLType(),buffobj->_components * buffobj->getSizeOfGLType() * chunksize,&cv[0]);
00789                         glBindBuffer(GL_ARRAY_BUFFER, 0);
00790                     }
00791                     if (attributestobeupdated[GLFeederInfo::ATT_VERTTEXTURE])
00792                     {
00793                         GLBufferObject* buffobj = _bo[GLFeederInfo::ATT_VERTTEXTURE];
00794                         glBindBuffer(GL_ARRAY_BUFFER, buffobj->_bohandle);
00795                         glBufferSubData(GL_ARRAY_BUFFER,chunkingpu * vertexchunk * buffobj->_components * buffobj->getSizeOfGLType(),buffobj->_components * buffobj->getSizeOfGLType() * chunksize,&tv[0]);
00796                         glBindBuffer(GL_ARRAY_BUFFER, 0);
00797                     }
00798                     glFinish();
00799                     ++chunkingpu;
00800                 }
00801             }
00802 
00803             pv.clear();
00804             nv.clear();
00805             cv.clear();
00806             tv.clear();
00807 
00808             chunkingpu = 0;
00809             std::vector<GLuint> ti(facechunk * 3);
00810             for(size_t i=0;i<tn;++i)
00811             {
00812                 size_t chunkindex = i % facechunk;
00813 
00814                 ti[chunkindex * 3 + 0] = GLuint(vcg::tri::Index(_mesh,_mesh.face[i].V(0)));
00815                 ti[chunkindex * 3 + 1] = GLuint(vcg::tri::Index(_mesh,_mesh.face[i].V(1)));
00816                 ti[chunkindex * 3 + 2] = GLuint(vcg::tri::Index(_mesh,_mesh.face[i].V(2)));
00817 
00818                 if((i == tn - 1) || (chunkindex == facechunk - 1))
00819                 {
00820                     size_t chunksize = facechunk;
00821                     if (i == tn - 1)
00822                         chunksize = chunkindex + 1;
00823 
00824                     if (attributestobeupdated[GLFeederInfo::ATT_VERTINDEX])
00825                     {
00826                         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _bo[GLFeederInfo::ATT_VERTINDEX]->_bohandle);
00827                         glBufferSubData(GL_ELEMENT_ARRAY_BUFFER,chunkingpu * facechunk *  _bo[GLFeederInfo::ATT_VERTINDEX]->_components *  _bo[GLFeederInfo::ATT_VERTINDEX]->getSizeOfGLType(),_bo[GLFeederInfo::ATT_VERTINDEX]->_components *  _bo[GLFeederInfo::ATT_VERTINDEX]->getSizeOfGLType() * chunksize,&ti[0]);
00828                         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
00829                     }
00830                     ++chunkingpu;
00831                 }
00832             }
00833             return true;
00834         }
00835 
00836         bool updateBuffersReplicatedPipeline(const std::vector<bool>& attributestobeupdated)
00837         {
00838             size_t tn = _mesh.fn;
00839 
00840             size_t facechunk = std::min(size_t(tn),_perbatchprim);
00841 
00842             std::vector<vcg::Point3f> rpv; //position vector
00843             if (attributestobeupdated[GLFeederInfo::ATT_VERTPOSITION])
00844                 rpv.resize(facechunk * 3);
00845 
00846             std::vector<vcg::Point3f> rnv; //per vertex normal vector
00847             if (attributestobeupdated[GLFeederInfo::ATT_VERTNORMAL])
00848                 rnv.resize(facechunk * 3);
00849 
00850             std::vector<vcg::Point3f> rfnv; //per face normal vector
00851             if (attributestobeupdated[GLFeederInfo::ATT_FACENORMAL])
00852                 rfnv.resize(facechunk * 3);
00853 
00854             std::vector<vcg::Color4b> rcv; // Per vertex color vector
00855             if (attributestobeupdated[GLFeederInfo::ATT_VERTCOLOR])
00856                 rcv.resize(facechunk * 3);
00857 
00858             std::vector<vcg::Color4b> rfcv; // Per vertex color vector
00859             if (attributestobeupdated[GLFeederInfo::ATT_FACECOLOR])
00860                 rfcv.resize(facechunk * 3);
00861 
00862             std::vector<float> rtv; // per vertex texture coord vector
00863             if (attributestobeupdated[GLFeederInfo::ATT_VERTTEXTURE])
00864                 rtv.resize(facechunk * 3 * 2);
00865 
00866             std::vector<float> rwtv; // per wedge texture coord vector
00867             if (attributestobeupdated[GLFeederInfo::ATT_WEDGETEXTURE])
00868                 rwtv.resize(facechunk * 3 * 2);
00869 
00870             size_t chunkingpu = 0;
00871 
00872             //it's a map containing for each texture seams n a vector of all the triangle index ranges having n has texture seam
00873             //Suppose that in a mesh we have
00874             //TXS_0{t0,t1,t2,t3}, TXS_4{t4,t5},TXS_0{t6},TXS_-1{t7,t8,t9},TXS_4{t10,t11}
00875             //so chunkMap will contain
00876             // -1 -> [<t7,t9>]
00877             //  0 -> [<t0,t3>,<t6,t6>]
00878             //  4 -> [<t4,t5>,<t10,t11>]
00879             //
00880             //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
00881 
00882 
00883             if (attributestobeupdated[GLFeederInfo::ATT_WEDGETEXTURE] || attributestobeupdated[GLFeederInfo::ATT_VERTTEXTURE])
00884             {
00885                 _chunkmap.clear();
00886                 if (attributestobeupdated[GLFeederInfo::ATT_WEDGETEXTURE])
00887                     fillchunkMap(_chunkmap);
00888                 else
00889                     if(attributestobeupdated[GLFeederInfo::ATT_VERTTEXTURE])
00890                         _chunkmap[0].push_back(std::make_pair(0,tn-1));
00891             }
00892 
00893             //default case: no texture is required to be rendered but a non texture attribute has to be updated
00894             //we have to init the _chunkmap with just one entry (-1...that means no texture) referring all the triangles in the mesh
00895             if ((!_currallocatedboatt[ATT_VERTTEXTURE] && !_currallocatedboatt[ATT_WEDGETEXTURE]) &&
00896                 (attributestobeupdated[GLFeederInfo::ATT_VERTPOSITION] ||
00897                 attributestobeupdated[GLFeederInfo::ATT_VERTNORMAL] || attributestobeupdated[GLFeederInfo::ATT_FACENORMAL] ||
00898                 attributestobeupdated[GLFeederInfo::ATT_VERTCOLOR] || attributestobeupdated[GLFeederInfo::ATT_FACECOLOR]))
00899             {
00900                 _chunkmap.clear();
00901                 _chunkmap[-1].push_back(std::make_pair(0,tn-1));
00902             }
00903 
00904             int t = 0;
00905             if (attributestobeupdated[GLFeederInfo::ATT_WEDGETEXTURE] || attributestobeupdated[GLFeederInfo::ATT_VERTTEXTURE])
00906             {
00907                 _texindnumtriangles.clear();
00908                 _texindnumtriangles.resize(_chunkmap.size());
00909             }
00910             int i = 0;
00911             size_t chunkindex = i;
00912             GLuint triangles = 0;
00913             for(ChunkMap::const_iterator mit = _chunkmap.begin();mit != _chunkmap.end();++mit)
00914             {
00915                 for (ChunkVector::const_iterator cit = mit->second.begin();cit != mit->second.end();++cit)
00916                 {
00917                     for(size_t indf = cit->first;indf<=cit->second;++indf)
00918                     {
00919                         chunkindex = i % facechunk;
00920                         if (attributestobeupdated[GLFeederInfo::ATT_VERTPOSITION])
00921                         {
00922                             rpv[chunkindex*3+0].Import(_mesh.face[indf].V(0)->P());
00923                             rpv[chunkindex*3+1].Import(_mesh.face[indf].V(1)->P());
00924                             rpv[chunkindex*3+2].Import(_mesh.face[indf].V(2)->P());
00925                         }
00926                         if (attributestobeupdated[GLFeederInfo::ATT_VERTNORMAL])
00927                         {
00928                             rnv[chunkindex*3+0].Import(_mesh.face[indf].V(0)->N().Normalize());
00929                             rnv[chunkindex*3+1].Import(_mesh.face[indf].V(1)->N().Normalize());
00930                             rnv[chunkindex*3+2].Import(_mesh.face[indf].V(2)->N().Normalize());
00931                         }
00932 
00933                         if (attributestobeupdated[GLFeederInfo::ATT_FACENORMAL])
00934                         {
00935                             rfnv[chunkindex*3+0].Import(_mesh.face[indf].N().Normalize());
00936                             rfnv[chunkindex*3+1].Import(_mesh.face[indf].N().Normalize());
00937                             rfnv[chunkindex*3+2].Import(_mesh.face[indf].N().Normalize());
00938                         }
00939 
00940                         if ((attributestobeupdated[GLFeederInfo::ATT_VERTCOLOR]))
00941                         {
00942                             rcv[chunkindex*3+0] = _mesh.face[indf].V(0)->C();
00943                             rcv[chunkindex*3+1] = _mesh.face[indf].V(1)->C();
00944                             rcv[chunkindex*3+2] = _mesh.face[indf].V(2)->C();
00945                         }
00946 
00947                         if ((attributestobeupdated[GLFeederInfo::ATT_FACECOLOR]))
00948                         {
00949                             rfcv[chunkindex*3+0] = _mesh.face[indf].C();
00950                             rfcv[chunkindex*3+1] = _mesh.face[indf].C();
00951                             rfcv[chunkindex*3+2] = _mesh.face[indf].C();
00952                         }
00953 
00954                         if (attributestobeupdated[GLFeederInfo::ATT_VERTTEXTURE])
00955                         {
00956                             rtv[chunkindex*6+0]=float(_mesh.face[indf].V(0)->T().U());
00957                             rtv[chunkindex*6+1]=float(_mesh.face[indf].V(0)->T().V());
00958                             rtv[chunkindex*6+2]=float(_mesh.face[indf].V(1)->T().U());
00959                             rtv[chunkindex*6+3]=float(_mesh.face[indf].V(1)->T().V());
00960                             rtv[chunkindex*6+4]=float(_mesh.face[indf].V(2)->T().U());
00961                             rtv[chunkindex*6+5]=float(_mesh.face[indf].V(2)->T().V());
00962                         }
00963 
00964                         if (attributestobeupdated[GLFeederInfo::ATT_WEDGETEXTURE])
00965                         {
00966                             rwtv[chunkindex*6+0]=float(_mesh.face[indf].WT(0).U());
00967                             rwtv[chunkindex*6+1]=float(_mesh.face[indf].WT(0).V());
00968                             rwtv[chunkindex*6+2]=float(_mesh.face[indf].WT(1).U());
00969                             rwtv[chunkindex*6+3]=float(_mesh.face[indf].WT(1).V());
00970                             rwtv[chunkindex*6+4]=float(_mesh.face[indf].WT(2).U());
00971                             rwtv[chunkindex*6+5]=float(_mesh.face[indf].WT(2).V());
00972                         }
00973 
00974                         if((i == tn - 1) || (chunkindex == facechunk - 1))
00975                         {
00976                             size_t chunksize = facechunk;
00977                             if (i == tn - 1)
00978                                 chunksize = chunkindex + 1;
00979 
00980                             if (attributestobeupdated[GLFeederInfo::ATT_VERTPOSITION])
00981                             {
00982                                 GLBufferObject* buffobj = _bo[GLFeederInfo::ATT_VERTPOSITION];
00983                                 glBindBuffer(GL_ARRAY_BUFFER, buffobj->_bohandle);
00984                                 glBufferSubData(GL_ARRAY_BUFFER,chunkingpu * facechunk * 3 * buffobj->_components * buffobj->getSizeOfGLType(),3 * buffobj->_components * buffobj->getSizeOfGLType() * chunksize,&rpv[0]);
00985                                 glBindBuffer(GL_ARRAY_BUFFER, 0);
00986                             }
00987 
00988                             if (attributestobeupdated[GLFeederInfo::ATT_VERTNORMAL])
00989                             {
00990                                 GLBufferObject* buffobj = _bo[GLFeederInfo::ATT_VERTNORMAL];
00991                                 glBindBuffer(GL_ARRAY_BUFFER, buffobj->_bohandle);
00992                                 glBufferSubData(GL_ARRAY_BUFFER,chunkingpu * facechunk * 3 * buffobj->_components * buffobj->getSizeOfGLType(),3 * buffobj->_components * buffobj->getSizeOfGLType() * chunksize,&rnv[0]);
00993                                 glBindBuffer(GL_ARRAY_BUFFER, 0);
00994                             }
00995 
00996                             if (attributestobeupdated[GLFeederInfo::ATT_FACENORMAL])
00997                             {
00998                                 GLBufferObject* buffobj = _bo[GLFeederInfo::ATT_FACENORMAL];
00999                                 glBindBuffer(GL_ARRAY_BUFFER, buffobj->_bohandle);
01000                                 glBufferSubData(GL_ARRAY_BUFFER,chunkingpu * facechunk * 3 * buffobj->_components * buffobj->getSizeOfGLType(),3 * buffobj->_components * buffobj->getSizeOfGLType() * chunksize,&rfnv[0]);
01001                                 glBindBuffer(GL_ARRAY_BUFFER, 0);
01002                             }
01003 
01004                             if (attributestobeupdated[GLFeederInfo::ATT_VERTCOLOR])
01005                             {
01006                                 GLBufferObject* buffobj = _bo[GLFeederInfo::ATT_VERTCOLOR];
01007                                 glBindBuffer(GL_ARRAY_BUFFER, buffobj->_bohandle);
01008                                 glBufferSubData(GL_ARRAY_BUFFER,chunkingpu * facechunk * 3 *buffobj->_components * buffobj->getSizeOfGLType(),3 * buffobj->_components * buffobj->getSizeOfGLType() * chunksize,&rcv[0]);
01009                                 glBindBuffer(GL_ARRAY_BUFFER, 0);
01010                             }
01011 
01012                             if (attributestobeupdated[GLFeederInfo::ATT_FACECOLOR])
01013                             {
01014                                 GLBufferObject* buffobj = _bo[GLFeederInfo::ATT_FACECOLOR];
01015                                 glBindBuffer(GL_ARRAY_BUFFER, buffobj->_bohandle);
01016                                 glBufferSubData(GL_ARRAY_BUFFER,chunkingpu * facechunk * 3 *buffobj->_components * buffobj->getSizeOfGLType(),3 * buffobj->_components * buffobj->getSizeOfGLType() * chunksize,&rfcv[0]);
01017                                 glBindBuffer(GL_ARRAY_BUFFER, 0);
01018                             }
01019 
01020                             if (attributestobeupdated[GLFeederInfo::ATT_VERTTEXTURE])
01021                             {
01022                                 GLBufferObject* buffobj = _bo[GLFeederInfo::ATT_VERTTEXTURE];
01023                                 glBindBuffer(GL_ARRAY_BUFFER, buffobj->_bohandle);
01024                                 glBufferSubData(GL_ARRAY_BUFFER,chunkingpu * facechunk * 3 *buffobj->_components * buffobj->getSizeOfGLType(),3 * buffobj->_components * buffobj->getSizeOfGLType() * chunksize,&rtv[0]);
01025                                 glBindBuffer(GL_ARRAY_BUFFER, 0);
01026                             }
01027 
01028                             if (attributestobeupdated[GLFeederInfo::ATT_WEDGETEXTURE])
01029                             {
01030                                 GLBufferObject* buffobj = _bo[GLFeederInfo::ATT_WEDGETEXTURE];
01031                                 glBindBuffer(GL_ARRAY_BUFFER, buffobj->_bohandle);
01032                                 glBufferSubData(GL_ARRAY_BUFFER,chunkingpu * facechunk * 3 *buffobj->_components * buffobj->getSizeOfGLType(),3 * buffobj->_components * buffobj->getSizeOfGLType() * chunksize,&rwtv[0]);
01033                                 glBindBuffer(GL_ARRAY_BUFFER, 0);
01034                             }
01035 
01036                             ++chunkingpu;
01037                         }
01038                         ++i;
01039                     }
01040                     triangles += cit->second - cit->first + 1;
01041                 }
01042 
01043                 if (attributestobeupdated[GLFeederInfo::ATT_WEDGETEXTURE] || attributestobeupdated[GLFeederInfo::ATT_VERTTEXTURE])
01044                     _texindnumtriangles[t] = std::make_pair(mit->first,triangles);
01045                 ++t;
01046             }
01047 
01048             //return (k != tn)
01049             //    throw MeshLabException("Mesh has not been properly partitioned");
01050             return true;
01051         }
01052 
01053         bool immediateModeRendering(const ReqAtts& req,const std::vector<GLuint>& textureindex = std::vector<GLuint>())
01054         {
01055             glPushAttrib(GL_ALL_ATTRIB_BITS);
01056             if(_mesh.fn==0)
01057                 return false;
01058 
01059             if(req[ATT_MESHCOLOR])
01060                 glColor(_mesh.C());
01061 
01062             //typename MESHTYPE::FaceContainer::iterator fp;
01063             typename MESHTYPE::FaceIterator fi = _mesh.face.begin();
01064 
01065             short curtexname=-1;
01066             if(req[ATT_WEDGETEXTURE])
01067             {
01068                 curtexname=(*fi).WT(0).n();
01069                 if ((curtexname >= 0) && (curtexname < (int)textureindex.size()))
01070                 {
01071                     glEnable(GL_TEXTURE_2D);
01072                     glBindTexture(GL_TEXTURE_2D,textureindex[curtexname]);
01073                 }
01074                 else
01075                 {
01076                     glDisable(GL_TEXTURE_2D);
01077                 }
01078             }
01079 
01080             if(req[ATT_VERTTEXTURE] && !textureindex.empty()) // in the case of per vertex tex coord we assume that we have a SINGLE texture.
01081             {
01082                 curtexname = 0;
01083                 glEnable(GL_TEXTURE_2D);
01084                 glBindTexture(GL_TEXTURE_2D,textureindex[curtexname]);
01085             }
01086 
01087             GLenum primitive = GL_TRIANGLES;
01088             if (req.primitiveModality() == vcg::GLFeederInfo::PR_POINTS)
01089                 primitive = GL_POINTS;
01090             glBegin(primitive);
01091 
01092             while(fi!=_mesh.face.end())
01093             {
01094                 typename MESHTYPE::FaceType & f = *fi;
01095                 if(!f.IsD())
01096                 {
01097                     if(req[ATT_WEDGETEXTURE])
01098                         if(f.WT(0).n() != curtexname)
01099                         {
01100                             curtexname=(*fi).WT(0).n();
01101                             glEnd();
01102 
01103                             if (curtexname >= 0)
01104                             {
01105                                 glEnable(GL_TEXTURE_2D);
01106                                 if(!textureindex.empty())
01107                                     glBindTexture(GL_TEXTURE_2D,textureindex[curtexname]);
01108                             }
01109                             else
01110                             {
01111                                 glDisable(GL_TEXTURE_2D);
01112                             }
01113 
01114                             glBegin(GL_TRIANGLES);
01115                         }
01116 
01117                         if(req[ATT_FACENORMAL])
01118                             glNormal(f.cN());
01119                         if(req[ATT_VERTNORMAL])
01120                             glNormal(f.V(0)->cN());
01121 
01122                         if(req[ATT_FACECOLOR])
01123                             glColor(f.C());
01124                         if(req[ATT_VERTCOLOR])
01125                             glColor(f.V(0)->C());
01126                         if(req[ATT_VERTTEXTURE])
01127                             glTexCoord(f.V(0)->T().P());
01128                         if(req[ATT_WEDGETEXTURE])
01129                             glTexCoord(f.WT(0).t(0));
01130                         glVertex(f.V(0)->P());
01131 
01132                         if(req[ATT_VERTNORMAL])
01133                             glNormal(f.V(1)->cN());
01134                         if(req[ATT_VERTCOLOR])
01135                             glColor(f.V(1)->C());
01136                         if(req[ATT_VERTTEXTURE])
01137                             glTexCoord(f.V(1)->T().P());
01138                         if(req[ATT_WEDGETEXTURE])
01139                             glTexCoord(f.WT(1).t(0));
01140                         glVertex(f.V(1)->P());
01141 
01142                         if(req[ATT_VERTNORMAL])
01143                             glNormal(f.V(2)->cN());
01144                         if(req[ATT_VERTCOLOR])
01145                             glColor(f.V(2)->C());
01146                         if(req[ATT_VERTTEXTURE])
01147                             glTexCoord(f.V(2)->T().P());
01148                         if(req[ATT_WEDGETEXTURE])
01149                             glTexCoord(f.WT(2).t(0));
01150                         glVertex(f.V(2)->P());
01151                 }
01152                 ++fi;
01153             }
01154 
01155             glEnd();
01156             glPopAttrib();
01157             return true;
01158         }
01159 
01160         void drawTriangles(const ReqAtts& req,const std::vector<GLuint>& textureindex = std::vector<GLuint>())
01161         {
01162             //isBORenderingPossible(
01163             if((!isPossibleToUseBORendering()) || (_mesh.VN() == 0))
01164                 return;
01165             updateClientState(req);
01166             bool replicated = ReqAtts::isReplicatedPipeline(_currallocatedboatt);
01167 
01168             if (replicated)
01169             {
01170                 //qDebug("Replicated drawing");
01171                 int firsttriangleoffset = 0;
01172                 if(!req[ATT_VERTTEXTURE] && !req[ATT_WEDGETEXTURE])
01173                 {
01174                     glDisable(GL_TEXTURE_2D);
01175                     glDrawArrays(GL_TRIANGLES,0,_mesh.fn * 3);
01176                 }
01177                 else
01178                 {
01179                     glEnable(GL_TEXTURE_2D);
01180                     for(std::vector< std::pair<short,GLuint> >::const_iterator it = _texindnumtriangles.begin();it != _texindnumtriangles.end();++it)
01181                     {
01182                         if ((it->first != -1) && (it->first < textureindex.size()))
01183                             glBindTexture(GL_TEXTURE_2D,textureindex[it->first]);
01184                         else
01185                             glBindTexture(GL_TEXTURE_2D,0);
01186                         glDrawArrays(GL_TRIANGLES,firsttriangleoffset,it->second * 3 - firsttriangleoffset);
01187                         firsttriangleoffset = it->second * 3;
01188                     }
01189                     glBindTexture(GL_TEXTURE_2D,0);
01190                     glDisable(GL_TEXTURE_2D);
01191                 }
01192 
01193             }
01194             else
01195             {
01196                 if(req[ATT_VERTTEXTURE])
01197                 {
01198                     if (textureindex.size() > 0)
01199                     {
01200                         glEnable(GL_TEXTURE_2D);
01201                         glBindTexture(GL_TEXTURE_2D,textureindex[0]);
01202 
01203                     }
01204                 }
01205                 else
01206                     glDisable(GL_TEXTURE_2D);
01207 
01208 
01209                 if  (_bo[ATT_VERTINDEX]->_isvalid)
01210                 {
01211                     //qDebug("Indexed drawing");
01212                     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,_bo[ATT_VERTINDEX]->_bohandle);
01213                     glDrawElements( GL_TRIANGLES, _mesh.fn * _bo[ATT_VERTINDEX]->_components,GL_UNSIGNED_INT ,NULL);
01214                     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
01215                 }
01216 
01217                 glBindTexture(GL_TEXTURE_2D,0);
01218                 glDisable(GL_TEXTURE_2D);
01219             }
01220             glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
01221             glBindBuffer(GL_ARRAY_BUFFER,0);
01222             int ii = 0;
01223             for(typename std::vector<GLBufferObject*>::const_iterator it = _bo.begin();it != _bo.end();++it)
01224             {
01225                 ATT_NAMES boname = static_cast<ATT_NAMES>(ii);
01226                 if ((boname != GLFeederInfo::ATT_VERTINDEX) && (boname != GLFeederInfo::ATT_MESHCOLOR))
01227                     disableClientState(boname,req);
01228                 ++ii;
01229             }
01230             /*disable all client state buffers*/
01231             ReqAtts tmp;
01232             updateClientState(tmp);
01233         }
01234 
01235         void drawPoints(const ReqAtts& req)
01236         {
01237             if ((!isPossibleToUseBORendering()) || (_mesh.VN() == 0))
01238                 return;
01239             updateClientState(req);
01240             glDisable(GL_TEXTURE_2D);
01241             //glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _bo[GLFeederInfo::ATT_VERTINDEX]->_bohandle);
01242             size_t pointsnum = _mesh.vn;
01243             if (ReqAtts::isReplicatedPipeline(_currallocatedboatt))
01244                 pointsnum = _mesh.fn * 3;
01245 
01246             glDrawArrays(GL_POINTS,0,pointsnum);
01247             //glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
01248 
01249             /*disable all client state buffers*/
01250             ReqAtts tmp;
01251             updateClientState(tmp);
01252         }
01253 
01254         void updateClientState(const ReqAtts& req)
01255         {
01256             int ii = 0;
01257             for(typename std::vector<GLBufferObject*>::const_iterator it = _bo.begin();it != _bo.end();++it)
01258             {
01259                 ATT_NAMES boname = static_cast<ATT_NAMES>(ii);
01260                 if ((boname != GLFeederInfo::ATT_VERTINDEX) && (boname != GLFeederInfo::ATT_MESHCOLOR))
01261                 {
01262                     if (req[boname] && _currallocatedboatt[boname] && (*it != NULL))
01263                     {
01264                         glBindBuffer((*it)->_target, (*it)->_bohandle);
01265                         setBufferPointer(boname);
01266                         glEnableClientState((*it)->_clientstatetag);
01267                         glBindBuffer((*it)->_target, 0);
01268                     }
01269                     else
01270                         disableClientState(boname,req);
01271                 }
01272                 ++ii;
01273             }
01274         }
01275 
01276         //bool isAttributeRequiredToBeDisplayed(ATT_NAMES att)
01277         //{
01278         //    bool res = false;
01279         //    for(std::map<unsigned int,ReqAtts>::const_iterator it = _allreqattsmap.begin();it != _allreqattsmap.end();++it)
01280         //        res |= it->second[att];
01281         //    return res;
01282         //}
01283 
01284         void setBufferPointer( ATT_NAMES boname) const
01285         {
01286             if ((boname < GLFeederInfo::ATT_VERTPOSITION) || (boname > GLFeederInfo::ATT_VERTINDEX))
01287                 return;
01288             GLBufferObject* cbo = _bo[boname];
01289             if (cbo == NULL)
01290                 return;
01291 
01292             switch(boname)
01293             {
01294             case(GLFeederInfo::ATT_VERTPOSITION):
01295                 {
01296                     glVertexPointer(cbo->_components, cbo->_gltype, 0, 0);
01297                     break;
01298                 }
01299             case(GLFeederInfo::ATT_VERTNORMAL):
01300             case(GLFeederInfo::ATT_FACENORMAL):
01301                 {
01302                     glNormalPointer(cbo->_gltype, 0, 0);
01303                     break;
01304                 }
01305             case(GLFeederInfo::ATT_VERTCOLOR):
01306             case(GLFeederInfo::ATT_FACECOLOR):
01307                 {
01308                     glColorPointer(cbo->_components, cbo->_gltype, 0, 0);
01309                     break;
01310                 }
01311             case(GLFeederInfo::ATT_VERTTEXTURE):
01312             case(GLFeederInfo::ATT_WEDGETEXTURE):
01313                 {
01314                     glTexCoordPointer(cbo->_components, cbo->_gltype, 0, 0);
01315                     break;
01316                 }
01317             case(GLFeederInfo::ATT_VERTINDEX):
01318                 {
01319                     break;
01320                 }
01321             default : break;
01322             }
01323         }
01324 
01325         void disableClientState( ATT_NAMES boname,const ReqAtts& req) const
01326         {
01327             if ((boname < GLFeederInfo::ATT_VERTPOSITION) || (boname > GLFeederInfo::ATT_VERTINDEX))
01328                 return;
01329 
01330             switch(boname)
01331             {
01332             case(GLFeederInfo::ATT_VERTPOSITION):
01333                 {
01334                     glDisableClientState(GL_VERTEX_ARRAY);
01335                     break;
01336                 }
01337             case(GLFeederInfo::ATT_VERTNORMAL):
01338             case(GLFeederInfo::ATT_FACENORMAL):
01339                 {
01340                     if (!req[GLFeederInfo::ATT_VERTNORMAL] && !req[GLFeederInfo::ATT_FACENORMAL])
01341                         glDisableClientState(GL_NORMAL_ARRAY);
01342                     break;
01343                 }
01344             case(GLFeederInfo::ATT_VERTCOLOR):
01345             case(GLFeederInfo::ATT_FACECOLOR):
01346                 {
01347                     if (!req[GLFeederInfo::ATT_VERTCOLOR] && !req[GLFeederInfo::ATT_FACECOLOR])
01348                         glDisableClientState(GL_COLOR_ARRAY);
01349                     break;
01350                 }
01351             case(GLFeederInfo::ATT_VERTTEXTURE):
01352             case(GLFeederInfo::ATT_WEDGETEXTURE):
01353                 {
01354                     if (!req[GLFeederInfo::ATT_VERTTEXTURE] && !req[GLFeederInfo::ATT_WEDGETEXTURE])
01355                         glDisableClientState(GL_TEXTURE_COORD_ARRAY);
01356                     break;
01357                 }
01358             default:
01359                 {
01360                     break;
01361                 }
01362 
01363             }
01364         }
01365 
01366         std::ptrdiff_t bufferObjectsMemoryRequired(const ReqAtts& rqatt) const
01367         {
01368             bool replicated = ReqAtts::isReplicatedPipeline(rqatt);
01369             std::ptrdiff_t result(0);
01370             bool generateindex = ReqAtts::isVertexIndexingRequired(rqatt);
01371 
01372             for(unsigned int ii = 0;ii < (unsigned int)ATT_NAMES_ARITY;++ii)
01373             {
01374                 ATT_NAMES nm = static_cast<ATT_NAMES>(ii);
01375                 if (rqatt[nm])
01376                     result += (std::ptrdiff_t) boExpectedDimension(nm,replicated,generateindex);
01377             }
01378             return result;
01379         }
01380 
01381         //expected number of cells should have the required bo
01382         //generateindex is true when i have a triangle based mesh
01383         //                              is false when i have a point based mesh
01384         size_t boExpectedSize(ATT_NAMES name,bool replicatedpipeline,bool generateindex) const
01385         {
01386             try
01387             {
01388                 GLBufferObject& cbo = *_bo.at(name);
01389                 size_t vertnum(_mesh.VN());
01390                 size_t facenum(_mesh.FN());
01391 
01392                 switch(name)
01393                 {
01394                 case(GLFeederInfo::ATT_VERTPOSITION):
01395                 case(GLFeederInfo::ATT_VERTNORMAL):
01396                 case(GLFeederInfo::ATT_VERTCOLOR):
01397                 case(GLFeederInfo::ATT_VERTTEXTURE):
01398                     {
01399                         if (replicatedpipeline)
01400                             return facenum * 3 * cbo._components;
01401                         else
01402                             return vertnum * cbo._components;
01403                     }
01404 
01405                 case(GLFeederInfo::ATT_FACENORMAL):
01406                 case(GLFeederInfo::ATT_FACECOLOR):
01407                 case(GLFeederInfo::ATT_WEDGETEXTURE):
01408                     {
01409                         if (replicatedpipeline)
01410                             return facenum * 3 * cbo._components;
01411                         else
01412                             return 0;
01413                     }
01414                 case(GLFeederInfo::ATT_VERTINDEX):
01415                     {
01416                         if (replicatedpipeline || !generateindex)
01417                             return 0;
01418                         else
01419                             return facenum * cbo._components;
01420                     }
01421                 default : break;
01422                 }
01423             }
01424             catch(std::out_of_range& /*exc*/)
01425             {
01426                 return 0;
01427             }
01428             return 0;
01429         }
01430 
01431         //generateindex is true when i have a triangle based mesh
01432         //                              is false when i have a point based mesh
01433         size_t boExpectedDimension(ATT_NAMES name,bool replicatedpipeline,bool generateindex) const
01434         {
01435             try
01436             {
01437                 size_t sz = boExpectedSize(name,replicatedpipeline,generateindex);
01438                 GLBufferObject* cbo = _bo.at(name);
01439                 if (cbo == NULL)
01440                     return 0;
01441                 else
01442                     return sz * cbo->getSizeOfGLType();
01443             }
01444             catch(std::out_of_range& /*exc*/)
01445             {
01446                 return 0;
01447             }
01448             return 0;
01449         }
01450 
01451         static bool isPerVertexAttribute(ATT_NAMES name)
01452         {
01453             return ((name == GLFeederInfo::ATT_VERTPOSITION) ||(name == GLFeederInfo::ATT_VERTNORMAL) || (name == GLFeederInfo::ATT_VERTCOLOR) || (name == GLFeederInfo::ATT_VERTTEXTURE));
01454         }
01455 
01456         //it's a map containing for each texture seams n a vector of all the triangle index ranges having n has texture seam
01457         //Suppose that in a mesh we have
01458         //TXS_0{t0,t1,t2,t3}, TXS_4{t4,t5},TXS_0{t6},TXS_-1{t7,t8,t9},TXS_4{t10,t11}
01459         //so chunkMap will contain
01460         // -1 -> [<t7,t9>]
01461         //  0 -> [<t0,t3>,<t6,t6>]
01462         //  4 -> [<t4,t5>,<t10,t11>]
01463 
01464         typedef std::vector< std::pair< GLuint,GLuint > > ChunkVector;
01465         typedef std::map< short, ChunkVector > ChunkMap;
01466 
01467         void fillchunkMap(ChunkMap& cmap)
01468         {
01469             if (!vcg::tri::HasPerWedgeTexCoord(_mesh))
01470                 return;
01471             cmap.clear();
01472             typename MESHTYPE::FaceIterator infrange = _mesh.face.begin();
01473             short texind = std::numeric_limits<short>::max();
01474             int hh = 0;
01475             for(typename MESHTYPE::FaceIterator fit = _mesh.face.begin();fit != _mesh.face.end();++fit)
01476             {
01477                 if (fit->WT(0).N() != texind)
01478                 {
01479                     if ((texind != std::numeric_limits<short>::max()) || (fit == _mesh.face.end() - 1))
01480                     {
01481                         GLuint lowind = std::distance(_mesh.face.begin(),infrange);
01482                         GLuint topind = std::distance(_mesh.face.begin(),fit) - 1;
01483                         cmap[texind].push_back(std::make_pair(lowind,topind));
01484                         infrange = fit;
01485                     }
01486                     texind = fit->WT(0).N();
01487                 }
01488                 ++hh;
01489             }
01490             cmap[texind].push_back(std::make_pair(std::distance(_mesh.face.begin(),infrange),std::distance(_mesh.face.begin(),_mesh.face.end() - 1)));
01491         }
01492 
01493         //ideally this should be const. I'm not yet sure if VCGLib will allow me to declare it as constant
01494         MESHTYPE& _mesh;
01495         MemoryInfo& _gpumeminfo;
01496 
01497         std::vector<GLBufferObject*> _bo;
01498 
01499         /*_currboatt contains the union of all the requested attributes by each single view on the scene. At the end it represents the BOs allocated in the GPU memory*/
01500         ReqAtts _currallocatedboatt;
01502         //std::map<unsigned int,ReqAtts> _allreqattsmap;
01503 
01504         std::vector< std::pair<short,GLuint> > _texindnumtriangles;
01505 
01506         bool _lastfeedingusedreplicatedpipeline;
01507         bool _borendering;
01508         size_t _perbatchprim;
01509         bool _rendermodinitialized;
01510         ChunkMap  _chunkmap;
01511     };
01512 }
01513 
01514 #endif


shape_reconstruction
Author(s): Roberto Martín-Martín
autogenerated on Sat Jun 8 2019 18:31:25