00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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
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,
00091 0x00000001,
00092 0x00000002,
00093 0x00000004,
00094 0x00000008,
00095 0x00000010,
00096 0x00000020};
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
00169
00170
00171
00172
00173
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
00226 template <typename MESHTYPE>
00227 class GLMeshAttributesFeeder : public GLFeederInfo
00228 {
00229 public:
00230 GLMeshAttributesFeeder( 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
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
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
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
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
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
00472
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
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
00522
00523 ((!(*it)->_isvalid) && (sz != (*it)->_size)) ||
00524
00525 (replicated && !_lastfeedingusedreplicatedpipeline && (isPerVertexAttribute(boname) || (boname == GLFeederInfo::ATT_VERTINDEX))) ||
00526
00527 (!replicated && _lastfeedingusedreplicatedpipeline) ||
00528
00529 (((*it)->_isvalid) && (sz != (*it)->_size))
00530
00531
00532
00533 ))
00534 {
00535 bufferDeAllocationRequested(boname);
00536 }
00537
00538
00539 if ((*it != NULL) && ( (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
00553
00554 if ((*it != NULL) && ((sz == (*it)->_size)))
00555 {
00557
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00572
00573 bufferDeAllocationRequested(boname);
00574 }
00575 ++ii;
00576 }
00577 _borendering = false;
00578 _lastfeedingusedreplicatedpipeline = false;
00579 return false;
00580 }
00581 else
00582 {
00583
00584
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
00596
00597
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
00607 GLenum err = glGetError();
00608 glBufferData(cbo->_target, dim, NULL, GL_STATIC_DRAW);
00609 err = glGetError();
00610
00611 failedallocation = (err == GL_OUT_OF_MEMORY);
00612 if (!failedallocation)
00613 {
00614
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
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
00642
00643
00644
00645
00646
00647 ++it;
00648 ++ii;
00649
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
00676
00677
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
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
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;
00722 if (attributestobeupdated[GLFeederInfo::ATT_VERTPOSITION])
00723 pv.resize(vertexchunk);
00724
00725 std::vector<vcg::Point3f> nv;
00726 if (attributestobeupdated[GLFeederInfo::ATT_VERTNORMAL])
00727 nv.resize(vertexchunk);
00728
00729 std::vector<vcg::Color4b> cv;
00730 if (attributestobeupdated[GLFeederInfo::ATT_VERTCOLOR])
00731 cv.resize(vertexchunk);
00732
00733 std::vector<float> tv;
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
00771
00772
00773
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;
00843 if (attributestobeupdated[GLFeederInfo::ATT_VERTPOSITION])
00844 rpv.resize(facechunk * 3);
00845
00846 std::vector<vcg::Point3f> rnv;
00847 if (attributestobeupdated[GLFeederInfo::ATT_VERTNORMAL])
00848 rnv.resize(facechunk * 3);
00849
00850 std::vector<vcg::Point3f> rfnv;
00851 if (attributestobeupdated[GLFeederInfo::ATT_FACENORMAL])
00852 rfnv.resize(facechunk * 3);
00853
00854 std::vector<vcg::Color4b> rcv;
00855 if (attributestobeupdated[GLFeederInfo::ATT_VERTCOLOR])
00856 rcv.resize(facechunk * 3);
00857
00858 std::vector<vcg::Color4b> rfcv;
00859 if (attributestobeupdated[GLFeederInfo::ATT_FACECOLOR])
00860 rfcv.resize(facechunk * 3);
00861
00862 std::vector<float> rtv;
00863 if (attributestobeupdated[GLFeederInfo::ATT_VERTTEXTURE])
00864 rtv.resize(facechunk * 3 * 2);
00865
00866 std::vector<float> rwtv;
00867 if (attributestobeupdated[GLFeederInfo::ATT_WEDGETEXTURE])
00868 rwtv.resize(facechunk * 3 * 2);
00869
00870 size_t chunkingpu = 0;
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
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
00894
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
01049
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
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())
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
01163 if((!isPossibleToUseBORendering()) || (_mesh.VN() == 0))
01164 return;
01165 updateClientState(req);
01166 bool replicated = ReqAtts::isReplicatedPipeline(_currallocatedboatt);
01167
01168 if (replicated)
01169 {
01170
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
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
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
01242 size_t pointsnum = _mesh.vn;
01243 if (ReqAtts::isReplicatedPipeline(_currallocatedboatt))
01244 pointsnum = _mesh.fn * 3;
01245
01246 glDrawArrays(GL_POINTS,0,pointsnum);
01247
01248
01249
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
01277
01278
01279
01280
01281
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
01382
01383
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& )
01425 {
01426 return 0;
01427 }
01428 return 0;
01429 }
01430
01431
01432
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& )
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
01457
01458
01459
01460
01461
01462
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
01494 MESHTYPE& _mesh;
01495 MemoryInfo& _gpumeminfo;
01496
01497 std::vector<GLBufferObject*> _bo;
01498
01499
01500 ReqAtts _currallocatedboatt;
01502
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