diff --git a/vcg/complex/algorithms/create/platonic.h b/vcg/complex/algorithms/create/platonic.h index 9d654e52..24f9333e 100644 --- a/vcg/complex/algorithms/create/platonic.h +++ b/vcg/complex/algorithms/create/platonic.h @@ -535,12 +535,8 @@ void OrientedCone(MeshType & m, typedef Matrix44 Matrix44x; Cone(m,r1,r2,Distance(origin,end),SubDiv); -// tri::UpdatePosition::Translate(m,CoordType(0,1,0)); -// tri::UpdatePosition::Scale(m,CoordType(1,0.5f,1)); -// tri::UpdatePosition::Scale(m,CoordType(xScale,1.0f,yScale)); + tri::UpdatePosition::Translate(m,CoordType(0,Distance(origin,end)/2,0)); -// float height = Distance(origin,end); -// tri::UpdatePosition::Scale(m,CoordType(radius,height,radius)); CoordType norm = end-origin; ScalarType angleRad = Angle(CoordType(0,1,0),norm); const ScalarType Delta= 0.000000001; @@ -560,7 +556,6 @@ void OrientedCone(MeshType & m, } tri::UpdatePosition::Matrix(m,rotM); tri::UpdatePosition::Translate(m,origin); - } diff --git a/vcg/complex/algorithms/curve_on_manifold.h b/vcg/complex/algorithms/curve_on_manifold.h index 61de82ac..ea6135ef 100644 --- a/vcg/complex/algorithms/curve_on_manifold.h +++ b/vcg/complex/algorithms/curve_on_manifold.h @@ -184,13 +184,12 @@ public: * */ - bool MarkFauxEdgeWithPolyLine(MeshType &poly) + bool MarkFauxEdgeWithPolyLine(MeshType &poly,bool markFlag=true) { - tri::UpdateFlags::FaceSetF(base); + if(markFlag) tri::UpdateFlags::FaceSetF(base); tri::UpdateTopology::VertexFace(base); tri::UpdateTopology::FaceFace(base); - - bool ret = true; + for(EdgeIterator ei=poly.edge.begin(); ei!=poly.edge.end();++ei) { CoordType ip0,ip1; @@ -201,23 +200,30 @@ public: { VertexPointer v0 = FindVertexSnap(f0,ip0); VertexPointer v1 = FindVertexSnap(f1,ip1); - assert(v0 != NULL && v1 != NULL && v0 != v1); + + if(v0==0 || v1==0) return false; + if(v0==v1) return false; + FacePointer ff0,ff1; int e0,e1; - ret &= face::FindSharedFaces(v0,v1,ff0,ff1,e0,e1); - if(ret) { + bool ret=face::FindSharedFaces(v0,v1,ff0,ff1,e0,e1); + if(ret){ + assert(ret); assert(ff0->V(e0)==v0 || ff0->V(e0)==v1); ff0->ClearF(e0); - ff1->ClearF(e1); + ff1->ClearF(e1); + } + else { + return false; } } - else - { - assert(0); - } + else { + return false; + } } - return ret; + return true; } + ScalarType MinDistOnEdge(CoordType samplePnt, EdgeGrid &edgeGrid, MeshType &poly, CoordType &closestPoint) { diff --git a/vcg/complex/algorithms/dual_meshing.h b/vcg/complex/algorithms/dual_meshing.h index 1a0f8ede..43c78542 100644 --- a/vcg/complex/algorithms/dual_meshing.h +++ b/vcg/complex/algorithms/dual_meshing.h @@ -48,6 +48,8 @@ class DualMeshing const PolyMeshType &primal, std::vector &vertSeq) { + (void)EdgeMap; + vcg::face::Pos startP(&startF,&startV); //get the star of pos diff --git a/vcg/complex/algorithms/parametrization/distortion.h b/vcg/complex/algorithms/parametrization/distortion.h index 95a980de..903d8553 100644 --- a/vcg/complex/algorithms/parametrization/distortion.h +++ b/vcg/complex/algorithms/parametrization/distortion.h @@ -385,7 +385,7 @@ public: ///return the number of folded faces - static bool Folded(const FaceType *f) + static bool IsFolded(const FaceType *f) { ScalarType areaUV=AreaUV(f); /*if (areaUV<0) @@ -393,32 +393,30 @@ public: return (areaUV<0); } - static int Folded(const MeshType &m) + static int FoldedNum(const MeshType &m) { int folded=0; - for (size_t i=0;i([&folded](const FaceType &f){ + if(IsFolded(&f)) folded++; + })); + return folded; } static bool GloballyUnFolded(const MeshType &m) { - int num=Folded(m); + int num=FoldedNum(m); return (num>(m.fn)/2); } static ScalarType MeshAngleDistortion(const MeshType &m) { ScalarType UDdist=0; - for (size_t i=0;i([&UDdist](const FaceType &f){ + UDdist += AngleDistortion(f)*Area3D(f); + })); + return UDdist; } diff --git a/vcg/complex/algorithms/parametrization/uv_utils.h b/vcg/complex/algorithms/parametrization/uv_utils.h index 53a46f8d..b813fa2d 100644 --- a/vcg/complex/algorithms/parametrization/uv_utils.h +++ b/vcg/complex/algorithms/parametrization/uv_utils.h @@ -24,7 +24,6 @@ #ifndef VCG_UV_UTILS #define VCG_UV_UTILS - namespace vcg { namespace tri{ template @@ -112,6 +111,26 @@ public: } } + static void GloballyRotate(MeshType &m,ScalarType Angle) + { + vcg::Box2 BB=PerWedgeUVBox(m); + UVCoordType Origin=BB.Center(); + typename MeshType::FaceIterator fi; + for (fi=m.face.begin();fi!=m.face.end();fi++) + { + if ((*fi).IsD()) continue; + for (int i=0;i<3;i++) + { + (*fi).WT(i).P()-=Origin; + ScalarType X1=(*fi).WT(i).P().X()*cos(Angle)-(*fi).WT(i).P().Y()*sin(Angle); + ScalarType Y1=(*fi).WT(i).P().X()*cos(Angle)+(*fi).WT(i).P().Y()*sin(Angle); + (*fi).WT(i).P().X()=X1; + (*fi).WT(i).P().Y()=Y1; + (*fi).WT(i).P()+=Origin; + } + } + } + static void LaplacianUVVert(MeshType &m,bool fix_borders=false,int steps=3) { FaceIterator fi; diff --git a/vcg/complex/algorithms/parametrization/voronoi_atlas.h b/vcg/complex/algorithms/parametrization/voronoi_atlas.h index 489d1513..345c5399 100644 --- a/vcg/complex/algorithms/parametrization/voronoi_atlas.h +++ b/vcg/complex/algorithms/parametrization/voronoi_atlas.h @@ -197,7 +197,7 @@ public: CollectUVBorder(rm,uvBorder); meshRegionVec.push_back(rm); uvBorders.push_back(uvBorder); - int foldedCnt = tri::Distortion::Folded(*rm); + int foldedCnt = tri::Distortion::FoldedNum(*rm); if( foldedCnt > rm->fn/10) { badRegionVec.push_back(rm); diff --git a/vcg/complex/algorithms/polygonal_algorithms.h b/vcg/complex/algorithms/polygonal_algorithms.h index 8c2f8b5b..e699cd40 100644 --- a/vcg/complex/algorithms/polygonal_algorithms.h +++ b/vcg/complex/algorithms/polygonal_algorithms.h @@ -29,7 +29,7 @@ #include #include #include - +#include #include //define a temporary triangle mesh type @@ -189,7 +189,7 @@ private: for (size_t i=0;iN(); + // for (int j=0;jN(); CoordType AVN=vcg::PolygonNormal(f); //AVN0.Normalize(); -// std::cout<<"AVN "<::VertexClearS(poly_m); + vcg::tri::UpdateTopology::FaceFace(poly_m); //UpdateBorderVertexFromPFFAdj(poly_m); vcg::tri::UpdateFlags::VertexBorderFromFaceAdj(poly_m); + std::vector > > SharpEdge(poly_m.vert.size()); + //first select sharp features + if (SharpDeg>0) + { + for (size_t i=0;i=poly_m.face[i].FFp(j))continue; + + CoordType N0=poly_m.face[i].N(); + CoordType N1=poly_m.face[i].FFp(j)->N(); + + ScalarType Angle=vcg::Angle(N0,N1); + if (fabs(Angle)>(SharpDeg* (M_PI / 180.0))) + { + CoordType Pos0=poly_m.face[i].V0(j)->P(); + CoordType Pos1=poly_m.face[i].V1(j)->P(); + CoordType Ori=Pos0; + CoordType Dir=Pos1-Pos0; + Dir.Normalize(); + vcg::Line3 L(Ori,Dir); + int Index0=vcg::tri::Index(poly_m,poly_m.face[i].V0(j)); + int Index1=vcg::tri::Index(poly_m,poly_m.face[i].V1(j)); + SharpEdge[Index0].push_back(L); + SharpEdge[Index1].push_back(L); + } + } + for (size_t i=0;i2)poly_m.vert[i].SetS(); + } + } + if (fixIrr) + { + vcg::tri::UpdateQuality::VertexValence(poly_m); + for (size_t i=0;i TriMeshGrid; TriMeshGrid grid; @@ -656,13 +713,13 @@ public: typename TriMeshType::FaceType *f=NULL; typename TriMeshType::CoordType norm,ip; f=vcg::tri::GetClosestFaceBase(tri_mesh,grid,testPos,MaxD,minDist,closestPt,norm,ip); - poly_m.vert[i].N().Import(norm); + //poly_m.vert[i].N().Import(norm); } for(int k=0;k0); + poly_m.vert[i].P()=av_closest/sum; + } } + UpdateFaceNormals(poly_m); + vcg::tri::UpdateNormal::PerVertexFromCurrentFaceNormal(poly_m); } + + } + + + template + static void TriangulateToTriMesh(PolyMeshType &poly_m,TriMeshType &triangle_mesh) + { + triangle_mesh.Clear(); + + PolyMeshType PolySwap; + vcg::tri::Append::Mesh(PolySwap,poly_m); + Triangulate(PolySwap); + + //then copy onto the triangle mesh + vcg::tri::Append::Mesh(triangle_mesh,PolySwap); } /*! \brief This function performs the polygon regularization as in "Statics Aware Grid Shells" @@ -688,18 +780,21 @@ public: static void SmoothReprojectPCA(PolyMeshType &poly_m, int relaxStep=100, bool fixIrr=false, - ScalarType Damp=0.5) + ScalarType Damp=0.5, + ScalarType SharpDeg=0, + bool WeightByQuality=false) { //transform into triangular TempMesh GuideSurf; - vcg::tri::PolygonSupport::ImportFromPolyMesh(GuideSurf,poly_m); + //vcg::tri::PolygonSupport:(GuideSurf,poly_m); + TriangulateToTriMesh(poly_m,GuideSurf); vcg::tri::UpdateBounding::Box(GuideSurf); vcg::tri::UpdateNormal::PerVertexNormalizedPerFace(GuideSurf); vcg::tri::UpdateTopology::FaceFace(GuideSurf); vcg::tri::UpdateFlags::FaceBorderFromFF(GuideSurf); //optimize it - vcg::PolygonalAlgorithm::SmoothReprojectPCA(poly_m,GuideSurf,relaxStep,fixIrr,Damp); + vcg::PolygonalAlgorithm::SmoothReprojectPCA(poly_m,GuideSurf,relaxStep,fixIrr,Damp,SharpDeg,WeightByQuality); } /*! \brief This function return average edge size @@ -711,7 +806,7 @@ public: for (size_t i=0;iP(); CoordType pos1=poly_m.face[i].cV((j+1)%NumV)->P(); @@ -763,7 +858,7 @@ public: //get vertices of the face int NumV=poly_m.face[i].VN(); - for (size_t j=0;j FaceV; - for (size_t j=0;jIsD()); @@ -813,7 +908,7 @@ public: } //then deallocate face - if (FaceV.size()==NumV)continue; + if ((int)FaceV.size()==NumV)continue; //otherwise deallocate and set new vertices poly_m.face[i].Dealloc(); @@ -922,10 +1017,10 @@ public: for (size_t i=0;iFFp(j); + if (f>f1)continue; + ScalarType L=(poly_m.face[i].P0(j)-poly_m.face[i].P1(j)).Norm(); + poly_m.face[i].V0(j)->Q()+=L; + poly_m.face[i].V1(j)->Q()+=L; + } + } + } + static void InterpolateQualityVertFormFaces(PolyMeshType &poly_m) { std::vector SumW(poly_m.vert.size(),0); @@ -1027,18 +1141,6 @@ public: Triangulate(poly_m,i); } - template - static void TriangulateToTriMesh(PolyMeshType &poly_m,TriMeshType &triangle_mesh) - { - triangle_mesh.Clear(); - - PolyMeshType PolySwap; - vcg::tri::Append::Mesh(PolySwap,poly_m); - Triangulate(PolySwap); - - //then copy onto the triangle mesh - vcg::tri::Append::Mesh(triangle_mesh,PolySwap); - } }; }//end namespace vcg diff --git a/vcg/complex/algorithms/quadrangulator.h b/vcg/complex/algorithms/quadrangulator.h index 46ce0831..3cc08097 100644 --- a/vcg/complex/algorithms/quadrangulator.h +++ b/vcg/complex/algorithms/quadrangulator.h @@ -135,7 +135,7 @@ private: { ScalarType minTolerance=precisionQ; //first add all eddge - for (int i=0;i WedgeInterp(vcg::TexCoord2 &t0, vcg::TexCoord2 &t1) { + (void)t0; + (void)t1; return (vcg::TexCoord2(0,0)); } @@ -440,7 +441,7 @@ private: for (int dir=0;dir<2;dir++) { ScalarType val0=uv.V(dir); - int integer0=floor(val0+0.5); + //int integer0=floor(val0+0.5); //if ((fabs(val0-(ScalarType)integer0))::FaceFace(Tmesh); // vcg::tri::UpdateFlags::FaceBorderFromFF(Tmesh); @@ -712,7 +713,7 @@ public: InitIntegerEdgesVert(Tmesh); - for (int i=0;i::Black, Color4b c2 = Color4::White, const bool ProcessSelected=false) +static int PerVertexThresholding(MeshType &m, float threshold, const Color4b c1 = Color4::Black, const Color4b c2 = Color4::White, const bool ProcessSelected=false) { RequirePerVertexColor(m); diff --git a/vcg/complex/allocate.h b/vcg/complex/allocate.h index 25cf2424..a04754c3 100644 --- a/vcg/complex/allocate.h +++ b/vcg/complex/allocate.h @@ -346,6 +346,17 @@ public: ei->V(1)=v1; return ei; } + + /** Function to add a single edge to the mesh. and initializing it with two indexes to the vertexes + */ + static EdgeIterator AddEdge(MeshType &m, size_t v0, size_t v1) + { + assert(v0!=v1); + assert(v0>=0 && v0=0 && v1=0 && v0<=m.vert.size()); - assert(v1>=0 && v1<=m.vert.size()); - assert(v2>=0 && v2<=m.vert.size()); + assert(v0>=0 && v0=0 && v1=0 && v2 - class PerViewData : public GLMeshAttributesInfo - { - public: + _perwire_wirewidth = opts._perwire_wirewidth; + } + }; - typedef GL_OPTIONS_DERIVED_TYPE GLOptionsType; + template + class PerViewData : public GLMeshAttributesInfo + { + public: - PerViewData() - :_pmmask(),_intatts(PR_ARITY),_glopts(NULL) - { - reset(); - } + typedef GL_OPTIONS_DERIVED_TYPE GLOptionsType; + + PerViewData() + :_pmmask(), _intatts(PR_ARITY), _glopts(NULL) + { + reset(); + } - PerViewData(const PerViewData& dt) - :_pmmask(dt._pmmask),_intatts(dt._intatts),_glopts(NULL) - { - if (dt._glopts != NULL) - _glopts = new GL_OPTIONS_DERIVED_TYPE(*(dt._glopts)); - } + PerViewData(const PerViewData& dt) + :_pmmask(dt._pmmask), _intatts(dt._intatts), _glopts(NULL) + { + if (dt._glopts != NULL) + _glopts = new GL_OPTIONS_DERIVED_TYPE(*(dt._glopts)); + } - ~PerViewData() - { - _intatts.clear(); - delete _glopts; - } + ~PerViewData() + { + _intatts.clear(); + delete _glopts; + } - PerViewData& operator=(const PerViewData& dt) - { - _pmmask = dt._pmmask; - _intatts = dt._intatts; - if (dt._glopts != NULL) - _glopts = new GL_OPTIONS_DERIVED_TYPE(*(dt._glopts)); - return (*this); - } + PerViewData& operator=(const PerViewData& dt) + { + _pmmask = dt._pmmask; + _intatts = dt._intatts; + if (dt._glopts != NULL) + _glopts = new GL_OPTIONS_DERIVED_TYPE(*(dt._glopts)); + return (*this); + } - bool set(PRIMITIVE_MODALITY pm,const RendAtts& atts) - { - size_t pmind(pm); - if (pm >= _intatts.size()) - return false; - //_pmmask.set(pm); - _intatts[pmind] = InternalRendAtts(atts,pm); - _pmmask.set(size_t(pm),_intatts[pmind][INT_ATT_NAMES::ATT_VERTPOSITION]); - return true; - } + bool set(PRIMITIVE_MODALITY pm, const RendAtts& atts) + { + size_t pmind(pm); + if (pm >= _intatts.size()) + return false; + //_pmmask.set(pm); + _intatts[pmind] = InternalRendAtts(atts, pm); + _pmmask.set(size_t(pm), _intatts[pmind][INT_ATT_NAMES::ATT_VERTPOSITION]); + return true; + } - bool set(PRIMITIVE_MODALITY pm,ATT_NAMES att,bool onoff) - { - size_t pmind(pm); - if (pm >= _intatts.size()) - return false; - _intatts[pmind][att] = onoff; - _pmmask.set(size_t(pm),_intatts[pmind][INT_ATT_NAMES::ATT_VERTPOSITION]); - if (_pmmask.test(size_t(pm))) - _intatts[pmind].setIndexingIfNeeded(pm); - return true; - } + bool set(PRIMITIVE_MODALITY pm, ATT_NAMES att, bool onoff) + { + size_t pmind(pm); + if (pm >= _intatts.size()) + return false; + _intatts[pmind][att] = onoff; + _pmmask.set(size_t(pm), _intatts[pmind][INT_ATT_NAMES::ATT_VERTPOSITION]); + if (_pmmask.test(size_t(pm))) + _intatts[pmind].setIndexingIfNeeded(pm); + return true; + } - bool set(PRIMITIVE_MODALITY pm,bool onoff) - { - return set(pm,INT_ATT_NAMES::ATT_VERTPOSITION,onoff); - } + bool set(PRIMITIVE_MODALITY pm, bool onoff) + { + return set(pm, INT_ATT_NAMES::ATT_VERTPOSITION, onoff); + } - void set(const GL_OPTIONS_DERIVED_TYPE& opts) - { - delete _glopts; - _glopts = new GL_OPTIONS_DERIVED_TYPE(opts); - } + void set(const GL_OPTIONS_DERIVED_TYPE& opts) + { + delete _glopts; + _glopts = new GL_OPTIONS_DERIVED_TYPE(opts); + } - bool isPrimitiveActive(PRIMITIVE_MODALITY pm) const - { - if (pm == PR_ARITY) - return false; - return (_pmmask.test(pm) && _intatts[size_t(pm)][INT_ATT_NAMES::ATT_VERTPOSITION]); - } + bool isPrimitiveActive(PRIMITIVE_MODALITY pm) const + { + if (pm == PR_ARITY) + return false; + return (_pmmask.test(pm) && _intatts[size_t(pm)][INT_ATT_NAMES::ATT_VERTPOSITION]); + } - PRIMITIVE_MODALITY_MASK getPrimitiveModalityMask() const - { - return _pmmask; - } + PRIMITIVE_MODALITY_MASK getPrimitiveModalityMask() const + { + return _pmmask; + } - bool get(PRIMITIVE_MODALITY pm,RendAtts& atts) const - { - size_t pmind(pm); - if (pm >= _intatts.size()) - return false; - atts = _intatts[pmind]; - return true; - } + bool get(PRIMITIVE_MODALITY pm, RendAtts& atts) const + { + size_t pmind(pm); + if (pm >= _intatts.size()) + return false; + atts = _intatts[pmind]; + return true; + } - bool get(GL_OPTIONS_DERIVED_TYPE& opts) const - { - if (_glopts == NULL) - return false; - opts = (*_glopts); - return true; - } + bool get(GL_OPTIONS_DERIVED_TYPE& opts) const + { + if (_glopts == NULL) + return false; + opts = (*_glopts); + return true; + } - void reset(bool deleteglopts = true) - { - _pmmask.reset(); - for(typename PerRendModData::iterator it = _intatts.begin();it != _intatts.end();++it) - it->reset(); - if (deleteglopts) - { - delete _glopts; - _glopts = 0; - } - } + void reset(bool deleteglopts = true) + { + _pmmask.reset(); + for (typename PerRendModData::iterator it = _intatts.begin(); it != _intatts.end(); ++it) + it->reset(); + if (deleteglopts) + { + delete _glopts; + _glopts = 0; + } + } - void serialize(std::string& str) - { - str.append(_pmmask.to_string()); - for (typename PerRendModData::iterator it = _intatts.begin(); it != _intatts.end(); ++it) - { - std::string s; - it->serialize(s); - str.append(s); - } - std::string s; - _glopts->serialize(s); - str.append(s); - } + void serialize(std::string& str) const + { + str.append(_pmmask.to_string()); + for (typename PerRendModData::const_iterator it = _intatts.begin(); it != _intatts.end(); ++it) + { + std::string s; + it->serialize(s); + str.append(s); + } + std::string s; + _glopts->serialize(s); + str.append(s); + } - bool deserialize(const std::string& str) - { - std::string::size_type pos = 0; - std::string token[6]; - token[0] = str.substr(pos, _pmmask.size()); - if (token[0].length() < _pmmask.size()) - return false; - int i = 1; - pos = _pmmask.size(); - for (typename PerRendModData::iterator it = _intatts.begin(); it != _intatts.end(); ++it, i++) - { - token[i] = str.substr(pos, InternalRendAtts::AttName::enumArity()); - if (token[i].length() < InternalRendAtts::AttName::enumArity()) - return false; - pos = pos + InternalRendAtts::AttName::enumArity(); - } - if (_glopts != NULL) - { - int size = _glopts->serialize(std::string()); - token[i] = str.substr(pos, size); - if (token[i].length() < size) - return false; - } - _pmmask = PRIMITIVE_MODALITY_MASK(token[0]); - i = 1; - for (typename PerRendModData::iterator it = _intatts.begin(); it != _intatts.end(); ++it, i++) - it->deserialize(token[i]); - if (_glopts != NULL) - _glopts->deserialize(token[i]); - return true; - } + bool deserialize(const std::string& str) + { + std::string::size_type pos = 0; + std::string token[6]; + token[0] = str.substr(pos, _pmmask.size()); + if (token[0].length() < _pmmask.size()) + return false; + int i = 1; + pos = _pmmask.size(); + for (typename PerRendModData::iterator it = _intatts.begin(); it != _intatts.end(); ++it, i++) + { + token[i] = str.substr(pos, InternalRendAtts::AttName::enumArity()); + if (token[i].length() < InternalRendAtts::AttName::enumArity()) + return false; + pos = pos + InternalRendAtts::AttName::enumArity(); + } + if (_glopts != NULL) + { + std::string tmp; + int size = _glopts->serialize(tmp); + token[i] = str.substr(pos, size); + if (token[i].length() < size) + return false; + } + _pmmask = PRIMITIVE_MODALITY_MASK(token[0]); + i = 1; + for (typename PerRendModData::iterator it = _intatts.begin(); it != _intatts.end(); ++it, i++) + it->deserialize(token[i]); + if (_glopts != NULL) + _glopts->deserialize(token[i]); + return true; + } - protected: - template friend class NotThreadSafeGLMeshAttributesMultiViewerBOManager; + protected: + template friend class NotThreadSafeGLMeshAttributesMultiViewerBOManager; - typedef std::vector PerRendModData; + typedef std::vector PerRendModData; - PRIMITIVE_MODALITY_MASK _pmmask; - PerRendModData _intatts; + PRIMITIVE_MODALITY_MASK _pmmask; + PerRendModData _intatts; - GL_OPTIONS_DERIVED_TYPE* _glopts; - }; + GL_OPTIONS_DERIVED_TYPE* _glopts; + }; - /****************************************************WARNING!!!!!!!!!!!!!!!!!*********************************************************************************************/ - //You must inherit from NotThreadSafeGLMeshAttributesMultiViewerBOManager, providing thread safe mechanisms, in order to use the bo facilities exposed by the class. - //In wrap/qt/qt_thread_safe_memory_rendering.h you will find a ready to use class based on QtConcurrency module. - /*************************************************************************************************************************************************************************/ - template - class NotThreadSafeGLMeshAttributesMultiViewerBOManager : public GLMeshAttributesInfo - { - public: - typedef PerViewData PVData; + /****************************************************WARNING!!!!!!!!!!!!!!!!!*********************************************************************************************/ + //You must inherit from NotThreadSafeGLMeshAttributesMultiViewerBOManager, providing thread safe mechanisms, in order to use the bo facilities exposed by the class. + //In wrap/qt/qt_thread_safe_memory_rendering.h you will find a ready to use class based on QtConcurrency module. + /*************************************************************************************************************************************************************************/ + template + class NotThreadSafeGLMeshAttributesMultiViewerBOManager : public GLMeshAttributesInfo + { + public: + typedef PerViewData PVData; - protected: - /****************************************************WARNING!!!!!!!!!!!!!!!!!*********************************************************************************************/ - //You must inherit from NotThreadSafeGLMeshAttributesMultiViewerBOManager, providing thread safe mechanisms, in order to use the bo facilities exposed by the class. - //In wrap/qt/qt_thread_safe_memory_rendering.h you will find a ready to use class based on QtConcurrency module. - /*************************************************************************************************************************************************************************/ + protected: + /****************************************************WARNING!!!!!!!!!!!!!!!!!*********************************************************************************************/ + //You must inherit from NotThreadSafeGLMeshAttributesMultiViewerBOManager, providing thread safe mechanisms, in order to use the bo facilities exposed by the class. + //In wrap/qt/qt_thread_safe_memory_rendering.h you will find a ready to use class based on QtConcurrency module. + /*************************************************************************************************************************************************************************/ - NotThreadSafeGLMeshAttributesMultiViewerBOManager(/*const*/ MESH_TYPE& mesh,MemoryInfo& meminfo, size_t perbatchprimitives) - :_mesh(mesh),_gpumeminfo(meminfo),_bo(INT_ATT_NAMES::enumArity(),NULL),_currallocatedboatt(),_perbatchprim(perbatchprimitives),_chunkmap(),_borendering(false),_edge(),_meshverticeswhenedgeindiceswerecomputed(0),_meshtriangleswhenedgeindiceswerecomputed(0),_tr(),_debugmode(false),_loginfo(),_meaningfulattsperprimitive(PR_ARITY,InternalRendAtts()) - { - _tr.SetIdentity(); - _bo[INT_ATT_NAMES::ATT_VERTPOSITION] = new GLBufferObject(3,GL_FLOAT,GL_VERTEX_ARRAY,GL_ARRAY_BUFFER); - _bo[INT_ATT_NAMES::ATT_VERTNORMAL] = new GLBufferObject(3,GL_FLOAT,GL_NORMAL_ARRAY,GL_ARRAY_BUFFER); - _bo[INT_ATT_NAMES::ATT_FACENORMAL] = new GLBufferObject(3,GL_FLOAT,GL_NORMAL_ARRAY,GL_ARRAY_BUFFER); - _bo[INT_ATT_NAMES::ATT_VERTCOLOR] = new GLBufferObject(4,GL_UNSIGNED_BYTE,GL_COLOR_ARRAY,GL_ARRAY_BUFFER); - _bo[INT_ATT_NAMES::ATT_FACECOLOR] = new GLBufferObject(4,GL_UNSIGNED_BYTE,GL_COLOR_ARRAY,GL_ARRAY_BUFFER); - /*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*/ - //_bo[INT_ATT_NAMES::ATT_FIXEDCOLOR] = NULL; - _bo[INT_ATT_NAMES::ATT_VERTTEXTURE] = new GLBufferObject(2,GL_FLOAT,GL_TEXTURE_COORD_ARRAY,GL_ARRAY_BUFFER); - _bo[INT_ATT_NAMES::ATT_WEDGETEXTURE] = new GLBufferObject(2,GL_FLOAT,GL_TEXTURE_COORD_ARRAY,GL_ARRAY_BUFFER); - _bo[INT_ATT_NAMES::ATT_VERTINDICES] = new GLBufferObject(3,GL_UNSIGNED_INT,GL_ELEMENT_ARRAY_BUFFER); - _bo[INT_ATT_NAMES::ATT_EDGEINDICES] = new GLBufferObject(2,GL_UNSIGNED_INT,GL_ELEMENT_ARRAY_BUFFER); + NotThreadSafeGLMeshAttributesMultiViewerBOManager(/*const*/ MESH_TYPE& mesh, MemoryInfo& meminfo, size_t perbatchprimitives) + :_mesh(mesh), _gpumeminfo(meminfo), _bo(INT_ATT_NAMES::enumArity(), NULL), _currallocatedboatt(), _perbatchprim(perbatchprimitives), _chunkmap(), _borendering(false), _edge(), _meshverticeswhenedgeindiceswerecomputed(0), _meshtriangleswhenedgeindiceswerecomputed(0), _tr(), _debugmode(false), _loginfo(), _meaningfulattsperprimitive(PR_ARITY, InternalRendAtts()) + { + _tr.SetIdentity(); + _bo[INT_ATT_NAMES::ATT_VERTPOSITION] = new GLBufferObject(3, GL_FLOAT, GL_VERTEX_ARRAY, GL_ARRAY_BUFFER); + _bo[INT_ATT_NAMES::ATT_VERTNORMAL] = new GLBufferObject(3, GL_FLOAT, GL_NORMAL_ARRAY, GL_ARRAY_BUFFER); + _bo[INT_ATT_NAMES::ATT_FACENORMAL] = new GLBufferObject(3, GL_FLOAT, GL_NORMAL_ARRAY, GL_ARRAY_BUFFER); + _bo[INT_ATT_NAMES::ATT_VERTCOLOR] = new GLBufferObject(4, GL_UNSIGNED_BYTE, GL_COLOR_ARRAY, GL_ARRAY_BUFFER); + _bo[INT_ATT_NAMES::ATT_FACECOLOR] = new GLBufferObject(4, GL_UNSIGNED_BYTE, GL_COLOR_ARRAY, GL_ARRAY_BUFFER); + /*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*/ + //_bo[INT_ATT_NAMES::ATT_FIXEDCOLOR] = NULL; + _bo[INT_ATT_NAMES::ATT_VERTTEXTURE] = new GLBufferObject(2, GL_FLOAT, GL_TEXTURE_COORD_ARRAY, GL_ARRAY_BUFFER); + _bo[INT_ATT_NAMES::ATT_WEDGETEXTURE] = new GLBufferObject(2, GL_FLOAT, GL_TEXTURE_COORD_ARRAY, GL_ARRAY_BUFFER); + _bo[INT_ATT_NAMES::ATT_VERTINDICES] = new GLBufferObject(3, GL_UNSIGNED_INT, GL_ELEMENT_ARRAY_BUFFER); + _bo[INT_ATT_NAMES::ATT_EDGEINDICES] = new GLBufferObject(2, GL_UNSIGNED_INT, GL_ELEMENT_ARRAY_BUFFER); - initMeaningfulAttsMask(); - } + initMeaningfulAttsMask(); + } - ~NotThreadSafeGLMeshAttributesMultiViewerBOManager() - { - _edge.clear(); - for(size_t ii = 0;ii < _bo.size();++ii) - delete _bo[ii]; - _bo.clear(); - } + ~NotThreadSafeGLMeshAttributesMultiViewerBOManager() + { + _edge.clear(); + for (size_t ii = 0; ii < _bo.size(); ++ii) + delete _bo[ii]; + _bo.clear(); + } - /*MeshAttributesUpdate will force the buffer allocation only of the bo rendered at least by one viewer. */ - /*If a filter add to a mesh, for instance, a per vertex color attribute that was not previously rendered, the meshAttributesUpdate() will ignore the attribute until a viewer require explicitly to render the per-vertex-color, too*/ - /*In order to do it, please, call the setPerViewRendAtts() setting up for at least one the existing viewer (or adding a new viewer) in the RendAtts reqatts parameter the reqatts[ATT_VERTCOLOR] to true value. */ - void meshAttributesUpdated(bool hasmeshconnectivitychanged,const RendAtts& changedrendatts) - { - InternalRendAtts tobeupdated(changedrendatts); - tobeupdated[INT_ATT_NAMES::ATT_VERTINDICES] = hasmeshconnectivitychanged; - tobeupdated[INT_ATT_NAMES::ATT_EDGEINDICES] = hasmeshconnectivitychanged; - for(unsigned int ii = 0;ii < INT_ATT_NAMES::enumArity();++ii) - { - INT_ATT_NAMES boname(ii); - if (_bo[boname] != NULL) - _bo[boname]->_isvalid = (_bo[boname]->_isvalid) && !(tobeupdated[boname]); - } - } + /*MeshAttributesUpdate will force the buffer allocation only of the bo rendered at least by one viewer. */ + /*If a filter add to a mesh, for instance, a per vertex color attribute that was not previously rendered, the meshAttributesUpdate() will ignore the attribute until a viewer require explicitly to render the per-vertex-color, too*/ + /*In order to do it, please, call the setPerViewRendAtts() setting up for at least one the existing viewer (or adding a new viewer) in the RendAtts reqatts parameter the reqatts[ATT_VERTCOLOR] to true value. */ + void meshAttributesUpdated(bool hasmeshconnectivitychanged, const RendAtts& changedrendatts) + { + InternalRendAtts tobeupdated(changedrendatts); + tobeupdated[INT_ATT_NAMES::ATT_VERTINDICES] = hasmeshconnectivitychanged; + tobeupdated[INT_ATT_NAMES::ATT_EDGEINDICES] = hasmeshconnectivitychanged; + for (unsigned int ii = 0; ii < INT_ATT_NAMES::enumArity(); ++ii) + { + INT_ATT_NAMES boname(ii); + if (_bo[boname] != NULL) + _bo[boname]->_isvalid = (_bo[boname]->_isvalid) && !(tobeupdated[boname]); + } + } - bool getPerViewInfo(UNIQUE_VIEW_ID_TYPE viewid,PVData& data) const - { - typename ViewsMap::const_iterator it = _perviewreqatts.find(viewid); - if (it == _perviewreqatts.end()) - return false; - data = it->second; - return true; - } + bool getPerViewInfo(UNIQUE_VIEW_ID_TYPE viewid, PVData& data) const + { + typename ViewsMap::const_iterator it = _perviewreqatts.find(viewid); + if (it == _perviewreqatts.end()) + return false; + data = it->second; + return true; + } - void setPerViewInfo(UNIQUE_VIEW_ID_TYPE viewid,const PVData& data) - { - ///cleanup stage...if an attribute impossible for a primitive modality is still here (it should not be...) we change the required atts into the view - PVData copydt(data); - for(PRIMITIVE_MODALITY pm = PRIMITIVE_MODALITY(0); pm < PR_ARITY;pm = next(pm)) - copydt._intatts[pm] = InternalRendAtts::intersectionSet(copydt._intatts[size_t(pm)],_meaningfulattsperprimitive[size_t(pm)]); - _perviewreqatts[viewid] = copydt; - } + void setPerViewInfo(UNIQUE_VIEW_ID_TYPE viewid, const PVData& data) + { + ///cleanup stage...if an attribute impossible for a primitive modality is still here (it should not be...) we change the required atts into the view + PVData copydt(data); + for (PRIMITIVE_MODALITY pm = PRIMITIVE_MODALITY(0); pm < PR_ARITY; pm = next(pm)) + copydt._intatts[pm] = InternalRendAtts::intersectionSet(copydt._intatts[size_t(pm)], _meaningfulattsperprimitive[size_t(pm)]); + _perviewreqatts[viewid] = copydt; + } void setPerAllViewsInfo(const PVData& data) { @@ -408,44 +409,44 @@ namespace vcg it->second = copydt; } - bool removeView(UNIQUE_VIEW_ID_TYPE viewid) - { - typename ViewsMap::iterator it = _perviewreqatts.find(viewid); - if (it == _perviewreqatts.end()) - return false; - _perviewreqatts.erase(viewid); - return true; - } + bool removeView(UNIQUE_VIEW_ID_TYPE viewid) + { + typename ViewsMap::iterator it = _perviewreqatts.find(viewid); + if (it == _perviewreqatts.end()) + return false; + _perviewreqatts.erase(viewid); + return true; + } - void removeAllViews() - { - _perviewreqatts.clear(); - } + void removeAllViews() + { + _perviewreqatts.clear(); + } - void draw(UNIQUE_VIEW_ID_TYPE viewid,const std::vector& textid = std::vector()) const - { - typename ViewsMap::const_iterator it = _perviewreqatts.find(viewid); - if (it == _perviewreqatts.end()) - return; + void draw(UNIQUE_VIEW_ID_TYPE viewid, const std::vector& textid = std::vector()) const + { + typename ViewsMap::const_iterator it = _perviewreqatts.find(viewid); + if (it == _perviewreqatts.end()) + return; - const PVData& dt = it->second; - //const InternalRendAtts& atts = it->second._intatts; + const PVData& dt = it->second; + //const InternalRendAtts& atts = it->second._intatts; drawFun(dt, textid); - } + } - - void drawAllocatedAttributesSubset(UNIQUE_VIEW_ID_TYPE viewid,const PVData& dt, const std::vector& textid = std::vector()) const + + void drawAllocatedAttributesSubset(UNIQUE_VIEW_ID_TYPE viewid, const PVData& dt, const std::vector& textid = std::vector()) const { typename ViewsMap::const_iterator it = _perviewreqatts.find(viewid); if (it == _perviewreqatts.end()) return; PVData tmp = dt; - + if (!(_currallocatedboatt[INT_ATT_NAMES::ATT_VERTPOSITION])) { for (PRIMITIVE_MODALITY pm = PRIMITIVE_MODALITY(0); pm < PR_ARITY; pm = next(pm)) - { + { tmp._pmmask[size_t(pm)] = 0; tmp._intatts[size_t(pm)] = InternalRendAtts(); } @@ -454,857 +455,857 @@ namespace vcg { for (PRIMITIVE_MODALITY pm = PRIMITIVE_MODALITY(0); pm < PR_ARITY; pm = next(pm)) { - tmp._intatts[size_t(pm)] = InternalRendAtts::intersectionSet(tmp._intatts[size_t(pm)],_meaningfulattsperprimitive[size_t(pm)]); - tmp._intatts[size_t(pm)] = InternalRendAtts::intersectionSet(tmp._intatts[size_t(pm)],_currallocatedboatt); + tmp._intatts[size_t(pm)] = InternalRendAtts::intersectionSet(tmp._intatts[size_t(pm)], _meaningfulattsperprimitive[size_t(pm)]); + tmp._intatts[size_t(pm)] = InternalRendAtts::intersectionSet(tmp._intatts[size_t(pm)], _currallocatedboatt); } } drawFun(dt, textid); } - bool isBORenderingAvailable() const - { - return _borendering; - } + bool isBORenderingAvailable() const + { + return _borendering; + } - bool manageBuffers() - { - InternalRendAtts tobeallocated; - InternalRendAtts tobedeallocated; - InternalRendAtts tobeupdated; - bool correctlyallocated = false; - bool arebuffersok = checkBuffersAllocationStatus(tobeallocated,tobedeallocated,tobeupdated); - if (!arebuffersok) - correctlyallocated = manageAndFeedBuffersIfNeeded(tobeallocated,tobedeallocated,tobeupdated); - if (_debugmode) - debug(tobeallocated,tobedeallocated,tobeupdated); - return (arebuffersok || correctlyallocated); - } - + bool manageBuffers() + { + InternalRendAtts tobeallocated; + InternalRendAtts tobedeallocated; + InternalRendAtts tobeupdated; + bool correctlyallocated = false; + bool arebuffersok = checkBuffersAllocationStatus(tobeallocated, tobedeallocated, tobeupdated); + if (!arebuffersok) + correctlyallocated = manageAndFeedBuffersIfNeeded(tobeallocated, tobedeallocated, tobeupdated); + if (_debugmode) + debug(tobeallocated, tobedeallocated, tobeupdated); + return (arebuffersok || correctlyallocated); + } - void setGLOptions(UNIQUE_VIEW_ID_TYPE viewid,const GL_OPTIONS_DERIVED_TYPE& opts) - { - typename ViewsMap::iterator it = _perviewreqatts.find(viewid); - if (it == _perviewreqatts.end()) - return; - it->second.set(opts); - } - void setTrMatrix(const vcg::Matrix44& tr) - { - _tr = tr; - } + void setGLOptions(UNIQUE_VIEW_ID_TYPE viewid, const GL_OPTIONS_DERIVED_TYPE& opts) + { + typename ViewsMap::iterator it = _perviewreqatts.find(viewid); + if (it == _perviewreqatts.end()) + return; + it->second.set(opts); + } - void setDebugMode(bool isdebug) - { - _debugmode = isdebug; - } + void setTrMatrix(const vcg::Matrix44& tr) + { + _tr = tr; + } - void getLog(DebugInfo& info) - { - info.reset(); - info._tobedeallocated = _loginfo._tobedeallocated; - info._tobeallocated = _loginfo._tobeallocated; - info._tobeupdated = _loginfo._tobeupdated; + void setDebugMode(bool isdebug) + { + _debugmode = isdebug; + } - info._currentlyallocated = _loginfo._currentlyallocated; - info._perviewdata = _loginfo._perviewdata; - _loginfo.reset(); - } + void getLog(DebugInfo& info) + { + info.reset(); + info._tobedeallocated = _loginfo._tobedeallocated; + info._tobeallocated = _loginfo._tobeallocated; + info._tobeupdated = _loginfo._tobeupdated; - private: - void initMeaningfulAttsMask() - { - _meaningfulattsperprimitive[PR_POINTS][INT_ATT_NAMES::ATT_VERTPOSITION] = true; - _meaningfulattsperprimitive[PR_POINTS][INT_ATT_NAMES::ATT_VERTNORMAL] = true; - _meaningfulattsperprimitive[PR_POINTS][INT_ATT_NAMES::ATT_VERTCOLOR] = true; - //_meaningfulattsperprimitive[PR_POINTS][INT_ATT_NAMES::ATT_FIXEDCOLOR] = true; - _meaningfulattsperprimitive[PR_POINTS][INT_ATT_NAMES::ATT_VERTTEXTURE] = true; + info._currentlyallocated = _loginfo._currentlyallocated; + info._perviewdata = _loginfo._perviewdata; + _loginfo.reset(); + } - _meaningfulattsperprimitive[PR_WIREFRAME_EDGES][INT_ATT_NAMES::ATT_VERTPOSITION] = true; - _meaningfulattsperprimitive[PR_WIREFRAME_EDGES][INT_ATT_NAMES::ATT_VERTNORMAL] = true; - _meaningfulattsperprimitive[PR_WIREFRAME_EDGES][INT_ATT_NAMES::ATT_VERTCOLOR] = true; - //_meaningfulattsperprimitive[PR_WIREFRAME_EDGES][INT_ATT_NAMES::ATT_FIXEDCOLOR] = true; - _meaningfulattsperprimitive[PR_WIREFRAME_EDGES][INT_ATT_NAMES::ATT_EDGEINDICES] = true; + private: + void initMeaningfulAttsMask() + { + _meaningfulattsperprimitive[PR_POINTS][INT_ATT_NAMES::ATT_VERTPOSITION] = true; + _meaningfulattsperprimitive[PR_POINTS][INT_ATT_NAMES::ATT_VERTNORMAL] = true; + _meaningfulattsperprimitive[PR_POINTS][INT_ATT_NAMES::ATT_VERTCOLOR] = true; + //_meaningfulattsperprimitive[PR_POINTS][INT_ATT_NAMES::ATT_FIXEDCOLOR] = true; + _meaningfulattsperprimitive[PR_POINTS][INT_ATT_NAMES::ATT_VERTTEXTURE] = true; - _meaningfulattsperprimitive[PR_WIREFRAME_TRIANGLES][INT_ATT_NAMES::ATT_VERTPOSITION] = true; - _meaningfulattsperprimitive[PR_WIREFRAME_TRIANGLES][INT_ATT_NAMES::ATT_VERTNORMAL] = true; - _meaningfulattsperprimitive[PR_WIREFRAME_TRIANGLES][INT_ATT_NAMES::ATT_VERTCOLOR] = true; - //_meaningfulattsperprimitive[PR_WIREFRAME_TRIANGLES][INT_ATT_NAMES::ATT_FIXEDCOLOR] = true; - _meaningfulattsperprimitive[PR_WIREFRAME_TRIANGLES][INT_ATT_NAMES::ATT_VERTINDICES] = true; + _meaningfulattsperprimitive[PR_WIREFRAME_EDGES][INT_ATT_NAMES::ATT_VERTPOSITION] = true; + _meaningfulattsperprimitive[PR_WIREFRAME_EDGES][INT_ATT_NAMES::ATT_VERTNORMAL] = true; + _meaningfulattsperprimitive[PR_WIREFRAME_EDGES][INT_ATT_NAMES::ATT_VERTCOLOR] = true; + //_meaningfulattsperprimitive[PR_WIREFRAME_EDGES][INT_ATT_NAMES::ATT_FIXEDCOLOR] = true; + _meaningfulattsperprimitive[PR_WIREFRAME_EDGES][INT_ATT_NAMES::ATT_EDGEINDICES] = true; - _meaningfulattsperprimitive[PR_SOLID][INT_ATT_NAMES::ATT_VERTPOSITION] = true; - _meaningfulattsperprimitive[PR_SOLID][INT_ATT_NAMES::ATT_VERTNORMAL] = true; - _meaningfulattsperprimitive[PR_SOLID][INT_ATT_NAMES::ATT_FACENORMAL] = true; - _meaningfulattsperprimitive[PR_SOLID][INT_ATT_NAMES::ATT_VERTCOLOR] = true; - _meaningfulattsperprimitive[PR_SOLID][INT_ATT_NAMES::ATT_FACECOLOR] = true; - //_meaningfulattsperprimitive[PR_SOLID][INT_ATT_NAMES::ATT_FIXEDCOLOR] = true; - _meaningfulattsperprimitive[PR_SOLID][INT_ATT_NAMES::ATT_VERTTEXTURE] = true; - _meaningfulattsperprimitive[PR_SOLID][INT_ATT_NAMES::ATT_WEDGETEXTURE] = true; - _meaningfulattsperprimitive[PR_SOLID][INT_ATT_NAMES::ATT_VERTINDICES] = true; - } + _meaningfulattsperprimitive[PR_WIREFRAME_TRIANGLES][INT_ATT_NAMES::ATT_VERTPOSITION] = true; + _meaningfulattsperprimitive[PR_WIREFRAME_TRIANGLES][INT_ATT_NAMES::ATT_VERTNORMAL] = true; + _meaningfulattsperprimitive[PR_WIREFRAME_TRIANGLES][INT_ATT_NAMES::ATT_VERTCOLOR] = true; + //_meaningfulattsperprimitive[PR_WIREFRAME_TRIANGLES][INT_ATT_NAMES::ATT_FIXEDCOLOR] = true; + _meaningfulattsperprimitive[PR_WIREFRAME_TRIANGLES][INT_ATT_NAMES::ATT_VERTINDICES] = true; - bool hasMeshAttribute(INT_ATT_NAMES attname) const - { - switch(attname) - { - case(INT_ATT_NAMES::ATT_VERTPOSITION): - return true; - case(INT_ATT_NAMES::ATT_VERTNORMAL): - return vcg::tri::HasPerVertexNormal(_mesh); - case(INT_ATT_NAMES::ATT_FACENORMAL): - return vcg::tri::HasPerFaceNormal(_mesh); - case(INT_ATT_NAMES::ATT_VERTCOLOR): - return vcg::tri::HasPerVertexColor(_mesh); - case(INT_ATT_NAMES::ATT_FACECOLOR): - return vcg::tri::HasPerFaceColor(_mesh); - /*case(INT_ATT_NAMES::ATT_FIXEDCOLOR): - return true;*/ - case(INT_ATT_NAMES::ATT_VERTTEXTURE): - return vcg::tri::HasPerVertexTexCoord(_mesh); - case(INT_ATT_NAMES::ATT_WEDGETEXTURE): - return vcg::tri::HasPerWedgeTexCoord(_mesh); - case(INT_ATT_NAMES::ATT_VERTINDICES): - return (_mesh.VN() != 0) && (_mesh.FN() != 0); - case(INT_ATT_NAMES::ATT_EDGEINDICES): - return vcg::tri::HasPerVertexFlags(_mesh) || ((_mesh.VN() != 0) && (_mesh.FN() == 0) && (_mesh.EN() == 0)); - default: - return false; - } - return false; - } + _meaningfulattsperprimitive[PR_SOLID][INT_ATT_NAMES::ATT_VERTPOSITION] = true; + _meaningfulattsperprimitive[PR_SOLID][INT_ATT_NAMES::ATT_VERTNORMAL] = true; + _meaningfulattsperprimitive[PR_SOLID][INT_ATT_NAMES::ATT_FACENORMAL] = true; + _meaningfulattsperprimitive[PR_SOLID][INT_ATT_NAMES::ATT_VERTCOLOR] = true; + _meaningfulattsperprimitive[PR_SOLID][INT_ATT_NAMES::ATT_FACECOLOR] = true; + //_meaningfulattsperprimitive[PR_SOLID][INT_ATT_NAMES::ATT_FIXEDCOLOR] = true; + _meaningfulattsperprimitive[PR_SOLID][INT_ATT_NAMES::ATT_VERTTEXTURE] = true; + _meaningfulattsperprimitive[PR_SOLID][INT_ATT_NAMES::ATT_WEDGETEXTURE] = true; + _meaningfulattsperprimitive[PR_SOLID][INT_ATT_NAMES::ATT_VERTINDICES] = true; + } - bool checkBuffersAllocationStatus(InternalRendAtts& tobeallocated,InternalRendAtts& tobedeallocated,InternalRendAtts& tobeupdated) const - { - bool somethingtodo = false; - tobedeallocated.reset(); - tobedeallocated.reset(); - tobeupdated.reset(); - - //bool thereisreplicatedview = isThereAReplicatedPipelineView(); - InternalRendAtts meaningfulrequiredbyatleastoneview; - InternalRendAtts probabilyuseless; - - for(typename ViewsMap::const_iterator it = _perviewreqatts.begin();it != _perviewreqatts.end();++it) - { - for(PRIMITIVE_MODALITY pm = PRIMITIVE_MODALITY(0); pm < PR_ARITY;pm = next(pm)) - { - //If a primitive_modality is not rendered (== no att_VERTPOSITION) all the referred attributes by this view can be eventually deallocated IF they are not used - //by some other rendered primitive - //the vertindices is, as usual, a different case - if (it->second._intatts[size_t(pm)][INT_ATT_NAMES::ATT_VERTPOSITION]) - meaningfulrequiredbyatleastoneview = InternalRendAtts::unionSet(meaningfulrequiredbyatleastoneview,it->second._intatts[size_t(pm)]); - else - probabilyuseless = InternalRendAtts::unionSet(probabilyuseless,it->second._intatts[size_t(pm)]); - } - } - bool thereisreplicatedview = InternalRendAtts::replicatedPipelineNeeded(meaningfulrequiredbyatleastoneview); - meaningfulrequiredbyatleastoneview[INT_ATT_NAMES::ATT_VERTINDICES] &= !thereisreplicatedview; - - InternalRendAtts reallyuseless = InternalRendAtts::complementSet(probabilyuseless,meaningfulrequiredbyatleastoneview); - - bool switchreplicatedindexed = (!InternalRendAtts::replicatedPipelineNeeded(_currallocatedboatt) && thereisreplicatedview) || (InternalRendAtts::replicatedPipelineNeeded(_currallocatedboatt) && !thereisreplicatedview); + bool hasMeshAttribute(INT_ATT_NAMES attname) const + { + switch (attname) + { + case(INT_ATT_NAMES::ATT_VERTPOSITION): + return true; + case(INT_ATT_NAMES::ATT_VERTNORMAL): + return vcg::tri::HasPerVertexNormal(_mesh); + case(INT_ATT_NAMES::ATT_FACENORMAL): + return vcg::tri::HasPerFaceNormal(_mesh); + case(INT_ATT_NAMES::ATT_VERTCOLOR): + return vcg::tri::HasPerVertexColor(_mesh); + case(INT_ATT_NAMES::ATT_FACECOLOR): + return vcg::tri::HasPerFaceColor(_mesh); + /*case(INT_ATT_NAMES::ATT_FIXEDCOLOR): + return true;*/ + case(INT_ATT_NAMES::ATT_VERTTEXTURE): + return vcg::tri::HasPerVertexTexCoord(_mesh); + case(INT_ATT_NAMES::ATT_WEDGETEXTURE): + return vcg::tri::HasPerWedgeTexCoord(_mesh); + case(INT_ATT_NAMES::ATT_VERTINDICES): + return (_mesh.VN() != 0) && (_mesh.FN() != 0); + case(INT_ATT_NAMES::ATT_EDGEINDICES): + return vcg::tri::HasPerVertexFlags(_mesh) || ((_mesh.VN() != 0) && (_mesh.FN() == 0) && (_mesh.EN() == 0)); + default: + return false; + } + return false; + } - /*in some way the vertices number changed. If i use the indexed pipeline i have to deallocate/allocate/update the vertex indices*/ - bool numvertchanged = boExpectedSize(INT_ATT_NAMES::ATT_VERTPOSITION,thereisreplicatedview) != _bo[INT_ATT_NAMES::ATT_VERTPOSITION]->_size; - bool vertindforcedupdate = numvertchanged && meaningfulrequiredbyatleastoneview[INT_ATT_NAMES::ATT_VERTINDICES]; + bool checkBuffersAllocationStatus(InternalRendAtts& tobeallocated, InternalRendAtts& tobedeallocated, InternalRendAtts& tobeupdated) const + { + bool somethingtodo = false; + tobedeallocated.reset(); + tobedeallocated.reset(); + tobeupdated.reset(); - InternalRendAtts probablytoallocate = InternalRendAtts::complementSet(meaningfulrequiredbyatleastoneview,_currallocatedboatt); - InternalRendAtts probablytodeallocate = InternalRendAtts::complementSet(_currallocatedboatt,meaningfulrequiredbyatleastoneview); - for(unsigned int ii = 0;ii < INT_ATT_NAMES::enumArity();++ii) - { - INT_ATT_NAMES boname(ii); - if (_bo[boname] != NULL) - { - bool hasmeshattribute = hasMeshAttribute(boname); - bool isvalid = (_bo[boname]->_isvalid); - bool notempty = (_bo[boname]->_size > 0); - if (boname != INT_ATT_NAMES::ATT_EDGEINDICES) - { - size_t sz = boExpectedSize(boname,thereisreplicatedview); + //bool thereisreplicatedview = isThereAReplicatedPipelineView(); + InternalRendAtts meaningfulrequiredbyatleastoneview; + InternalRendAtts probabilyuseless; - tobedeallocated[boname] = (notempty && !hasmeshattribute) || - (notempty && probablytodeallocate[boname]) || - (notempty && reallyuseless[boname]) || - (notempty && (_bo[boname]->_size != sz) && meaningfulrequiredbyatleastoneview[boname]) || - (notempty && (boname == INT_ATT_NAMES::ATT_VERTINDICES) && (vertindforcedupdate)); - tobeallocated[boname] = (hasmeshattribute && (sz > 0) && (sz != _bo[boname]->_size) && meaningfulrequiredbyatleastoneview[boname]) || - (hasmeshattribute && (sz > 0) && probablytoallocate[boname]) || - (hasmeshattribute && (boname == INT_ATT_NAMES::ATT_VERTINDICES) && (vertindforcedupdate)); - tobeupdated[boname] = tobeallocated[boname] || (hasmeshattribute && (sz > 0) && !(isvalid) && meaningfulrequiredbyatleastoneview[boname]); - } - else - { - bool meshchanged = ((_mesh.FN() != _meshtriangleswhenedgeindiceswerecomputed) || (_mesh.VN() != _meshverticeswhenedgeindiceswerecomputed)); - tobedeallocated[INT_ATT_NAMES::ATT_EDGEINDICES] = (notempty && !hasmeshattribute) || - (notempty && !meaningfulrequiredbyatleastoneview[INT_ATT_NAMES::ATT_EDGEINDICES]) || - (notempty && !(isvalid) && meshchanged); - tobeallocated[INT_ATT_NAMES::ATT_EDGEINDICES] = (hasmeshattribute && meaningfulrequiredbyatleastoneview[INT_ATT_NAMES::ATT_EDGEINDICES] && !(isvalid) && (meshchanged)) || - (hasmeshattribute && meaningfulrequiredbyatleastoneview[INT_ATT_NAMES::ATT_EDGEINDICES] && !(isvalid) && !(_currallocatedboatt[INT_ATT_NAMES::ATT_EDGEINDICES])); - tobeupdated[INT_ATT_NAMES::ATT_EDGEINDICES] = tobeallocated[INT_ATT_NAMES::ATT_EDGEINDICES] || - (hasmeshattribute && !(isvalid) && meaningfulrequiredbyatleastoneview[INT_ATT_NAMES::ATT_EDGEINDICES]) || - (hasmeshattribute && switchreplicatedindexed && meaningfulrequiredbyatleastoneview[INT_ATT_NAMES::ATT_EDGEINDICES]); - } - } - somethingtodo = somethingtodo || tobeallocated[boname] || tobedeallocated[boname] || tobeupdated[boname]; - } - return !(somethingtodo); - } + for (typename ViewsMap::const_iterator it = _perviewreqatts.begin(); it != _perviewreqatts.end(); ++it) + { + for (PRIMITIVE_MODALITY pm = PRIMITIVE_MODALITY(0); pm < PR_ARITY; pm = next(pm)) + { + //If a primitive_modality is not rendered (== no att_VERTPOSITION) all the referred attributes by this view can be eventually deallocated IF they are not used + //by some other rendered primitive + //the vertindices is, as usual, a different case + if (it->second._intatts[size_t(pm)][INT_ATT_NAMES::ATT_VERTPOSITION]) + meaningfulrequiredbyatleastoneview = InternalRendAtts::unionSet(meaningfulrequiredbyatleastoneview, it->second._intatts[size_t(pm)]); + else + probabilyuseless = InternalRendAtts::unionSet(probabilyuseless, it->second._intatts[size_t(pm)]); + } + } + bool thereisreplicatedview = InternalRendAtts::replicatedPipelineNeeded(meaningfulrequiredbyatleastoneview); + meaningfulrequiredbyatleastoneview[INT_ATT_NAMES::ATT_VERTINDICES] &= !thereisreplicatedview; - bool manageAndFeedBuffersIfNeeded(const InternalRendAtts& tobeallocated,const InternalRendAtts& tobedeallocated,const InternalRendAtts& tobeupdated) - { - if (tobeupdated[INT_ATT_NAMES::ATT_EDGEINDICES]) - updateEdgeVertIndVector(); + InternalRendAtts reallyuseless = InternalRendAtts::complementSet(probabilyuseless, meaningfulrequiredbyatleastoneview); - bool immediatemode = !(buffersMemoryManagementFunction(tobeallocated,tobedeallocated,tobeupdated)); - bool replicated = isThereAReplicatedPipelineView(); + bool switchreplicatedindexed = (!InternalRendAtts::replicatedPipelineNeeded(_currallocatedboatt) && thereisreplicatedview) || (InternalRendAtts::replicatedPipelineNeeded(_currallocatedboatt) && !thereisreplicatedview); - if (immediatemode) - return false; + /*in some way the vertices number changed. If i use the indexed pipeline i have to deallocate/allocate/update the vertex indices*/ + bool numvertchanged = boExpectedSize(INT_ATT_NAMES::ATT_VERTPOSITION, thereisreplicatedview) != _bo[INT_ATT_NAMES::ATT_VERTPOSITION]->_size; + bool vertindforcedupdate = numvertchanged && meaningfulrequiredbyatleastoneview[INT_ATT_NAMES::ATT_VERTINDICES]; - bool somethingtoupdate = false; - for(unsigned int hh = 0;hh < INT_ATT_NAMES::enumArity();++hh) - somethingtoupdate = somethingtoupdate || tobeupdated[hh]; + InternalRendAtts probablytoallocate = InternalRendAtts::complementSet(meaningfulrequiredbyatleastoneview, _currallocatedboatt); + InternalRendAtts probablytodeallocate = InternalRendAtts::complementSet(_currallocatedboatt, meaningfulrequiredbyatleastoneview); + for (unsigned int ii = 0; ii < INT_ATT_NAMES::enumArity(); ++ii) + { + INT_ATT_NAMES boname(ii); + if (_bo[boname] != NULL) + { + bool hasmeshattribute = hasMeshAttribute(boname); + bool isvalid = (_bo[boname]->_isvalid); + bool notempty = (_bo[boname]->_size > 0); + if (boname != INT_ATT_NAMES::ATT_EDGEINDICES) + { + size_t sz = boExpectedSize(boname, thereisreplicatedview); - if (somethingtoupdate) - { - if (replicated) - { - InternalRendAtts attributestobeupdated(tobeupdated); - //WARNING!In case we have to update the wedgetexture bo maybe (not always!) we must update also the other buffer already in memory - //cause the wedgetexture pipeline force a change in the order of the triangles in GPU. - //they are now ordered by the texture seam and not more by the triangle index! - if (tobeupdated[INT_ATT_NAMES::ATT_WEDGETEXTURE]) - attributestobeupdated = _currallocatedboatt; - updateBuffersReplicatedPipeline(attributestobeupdated); - } - else - updateBuffersIndexedPipeline(tobeupdated); - glFinish(); - } - return true; - } + tobedeallocated[boname] = (notempty && !hasmeshattribute) || + (notempty && probablytodeallocate[boname]) || + (notempty && reallyuseless[boname]) || + (notempty && (_bo[boname]->_size != sz) && meaningfulrequiredbyatleastoneview[boname]) || + (notempty && (boname == INT_ATT_NAMES::ATT_VERTINDICES) && (vertindforcedupdate)); + tobeallocated[boname] = (hasmeshattribute && (sz > 0) && (sz != _bo[boname]->_size) && meaningfulrequiredbyatleastoneview[boname]) || + (hasmeshattribute && (sz > 0) && probablytoallocate[boname]) || + (hasmeshattribute && (boname == INT_ATT_NAMES::ATT_VERTINDICES) && (vertindforcedupdate)); + tobeupdated[boname] = tobeallocated[boname] || (hasmeshattribute && (sz > 0) && !(isvalid) && meaningfulrequiredbyatleastoneview[boname]); + } + else + { + bool meshchanged = ((_mesh.FN() != _meshtriangleswhenedgeindiceswerecomputed) || (_mesh.VN() != _meshverticeswhenedgeindiceswerecomputed)); + tobedeallocated[INT_ATT_NAMES::ATT_EDGEINDICES] = (notempty && !hasmeshattribute) || + (notempty && !meaningfulrequiredbyatleastoneview[INT_ATT_NAMES::ATT_EDGEINDICES]) || + (notempty && !(isvalid) && meshchanged); + tobeallocated[INT_ATT_NAMES::ATT_EDGEINDICES] = (hasmeshattribute && meaningfulrequiredbyatleastoneview[INT_ATT_NAMES::ATT_EDGEINDICES] && !(isvalid) && (meshchanged)) || + (hasmeshattribute && meaningfulrequiredbyatleastoneview[INT_ATT_NAMES::ATT_EDGEINDICES] && !(isvalid) && !(_currallocatedboatt[INT_ATT_NAMES::ATT_EDGEINDICES])); + tobeupdated[INT_ATT_NAMES::ATT_EDGEINDICES] = tobeallocated[INT_ATT_NAMES::ATT_EDGEINDICES] || + (hasmeshattribute && !(isvalid) && meaningfulrequiredbyatleastoneview[INT_ATT_NAMES::ATT_EDGEINDICES]) || + (hasmeshattribute && switchreplicatedindexed && meaningfulrequiredbyatleastoneview[INT_ATT_NAMES::ATT_EDGEINDICES]); + } + } + somethingtodo = somethingtodo || tobeallocated[boname] || tobedeallocated[boname] || tobeupdated[boname]; + } + return !(somethingtodo); + } - void updateEdgeVertIndVector() - { - _edge.clear(); - fillUniqueEdgeVector(_mesh,_edge); - _meshverticeswhenedgeindiceswerecomputed = _mesh.VN(); - _meshtriangleswhenedgeindiceswerecomputed = _mesh.FN(); - } + bool manageAndFeedBuffersIfNeeded(const InternalRendAtts& tobeallocated, const InternalRendAtts& tobedeallocated, const InternalRendAtts& tobeupdated) + { + if (tobeupdated[INT_ATT_NAMES::ATT_EDGEINDICES]) + updateEdgeVertIndVector(); - bool buffersMemoryManagementFunction(const InternalRendAtts& tobeallocated,const InternalRendAtts& tobedeallocated,const InternalRendAtts& tobeupdated) - { - //GLenum err = glGetError(); - bool replicated = isThereAReplicatedPipelineView(); - std::ptrdiff_t newallocatedmem = bufferObjectsMemoryRequired(tobeallocated); - std::ptrdiff_t deallocatedmem = bufferObjectsMemoryRequired(tobedeallocated); - ptrdiff_t zero = 0; - std::ptrdiff_t changedsize = std::max(zero,newallocatedmem - deallocatedmem); - //std::ptrdiff_t bomemoryrequiredbymesh = bufferObjectsMemoryRequired(_currallocatedboatt) - deallocatedmem + newallocatedmem; - unsigned int ii = 0; - for(typename std::vector::iterator it = _bo.begin();it != _bo.end();++it) - { - INT_ATT_NAMES boname(ii); - //size_t sz = boExpectedSize(boname,replicated); - //size_t dim = boExpectedDimension(boname,replicated); + bool immediatemode = !(buffersMemoryManagementFunction(tobeallocated, tobedeallocated, tobeupdated)); + bool replicated = isThereAReplicatedPipelineView(); - if (tobedeallocated[boname]) - bufferDeAllocationRequested(boname); - ++ii; - } + if (immediatemode) + return false; - if (!_gpumeminfo.isAdditionalMemoryAvailable(changedsize)) - { - std::cout << "no additional memory available!!! memory required: " << changedsize << std::endl; - ii = 0; - for(typename std::vector::iterator it = _bo.begin();it != _bo.end();++it) - { - INT_ATT_NAMES boname(ii); - size_t sz(boExpectedSize(boname,replicated)); - //there are already valid mesh attributes properly allocated in memory but there is not enough gpu memory for the remaining mesh. - //we have to deallocate the previously allocated mesh attributes - if ((*it != NULL) && ((sz == (*it)->_size))) - bufferDeAllocationRequested(boname); - ++ii; - } - _borendering = false; - return false; - } - else - { - bool failedallocation = false; - unsigned int ii = 0; - typename std::vector::iterator it = _bo.begin(); - while((it != _bo.end()) && (!failedallocation)) - { - INT_ATT_NAMES boname(ii); - GLBufferObject* cbo = _bo[ii]; - if (tobeallocated[boname]) - { - cbo->_size = boExpectedSize(boname,replicated); - std::ptrdiff_t dim = boExpectedDimension(boname,replicated); - glGenBuffers(1, &cbo->_bohandle); - glBindBuffer(cbo->_target, cbo->_bohandle); - //we call glGetError BEFORE the glBufferData function in order to clean the error flag - GLenum err = glGetError(); - //assert(err == GL_NO_ERROR); - glBufferData(cbo->_target, dim, NULL, GL_STATIC_DRAW); - err = glGetError(); - //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 - failedallocation = (err == GL_OUT_OF_MEMORY) || (!_gpumeminfo.isAdditionalMemoryAvailable(dim)); - if (!failedallocation) - { - //setBufferPointerEnableClientState(boname); - setBufferPointer(boname); - _gpumeminfo.acquiredMemory(dim); - } - cbo->_isvalid = !failedallocation; - _borendering = !failedallocation; - glBindBuffer(cbo->_target, 0); - _currallocatedboatt[boname] = !failedallocation; - } - else - { - //the arity of the attribute contained in the bo didn't change so i can use the old space without reallocating it - if (cbo != NULL) - cbo->_isvalid = cbo->_isvalid || tobeupdated[boname]; - } - ++it; - ++ii; - } - if (failedallocation) - buffersDeAllocationRequested(_currallocatedboatt); - _borendering = !failedallocation; - } - return _borendering; - } + bool somethingtoupdate = false; + for (unsigned int hh = 0; hh < INT_ATT_NAMES::enumArity(); ++hh) + somethingtoupdate = somethingtoupdate || tobeupdated[hh]; - bool updateBuffersIndexedPipeline(const InternalRendAtts& attributestobeupdated) - { - _chunkmap.clear(); - size_t vn = _mesh.VN(); - size_t tn = _mesh.FN(); + if (somethingtoupdate) + { + if (replicated) + { + InternalRendAtts attributestobeupdated(tobeupdated); + //WARNING!In case we have to update the wedgetexture bo maybe (not always!) we must update also the other buffer already in memory + //cause the wedgetexture pipeline force a change in the order of the triangles in GPU. + //they are now ordered by the texture seam and not more by the triangle index! + if (tobeupdated[INT_ATT_NAMES::ATT_WEDGETEXTURE]) + attributestobeupdated = _currallocatedboatt; + updateBuffersReplicatedPipeline(attributestobeupdated); + } + else + updateBuffersIndexedPipeline(tobeupdated); + glFinish(); + } + return true; + } - size_t facechunk = std::min(size_t(tn),_perbatchprim); - size_t vertexchunk = std::min(size_t(vn),_perbatchprim); + void updateEdgeVertIndVector() + { + _edge.clear(); + fillUniqueEdgeVector(_mesh, _edge); + _meshverticeswhenedgeindiceswerecomputed = _mesh.VN(); + _meshtriangleswhenedgeindiceswerecomputed = _mesh.FN(); + } - std::vector pv; //position vector - if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTPOSITION]) - pv.resize(vertexchunk); + bool buffersMemoryManagementFunction(const InternalRendAtts& tobeallocated, const InternalRendAtts& tobedeallocated, const InternalRendAtts& tobeupdated) + { + //GLenum err = glGetError(); + bool replicated = isThereAReplicatedPipelineView(); + std::ptrdiff_t newallocatedmem = bufferObjectsMemoryRequired(tobeallocated); + std::ptrdiff_t deallocatedmem = bufferObjectsMemoryRequired(tobedeallocated); + ptrdiff_t zero = 0; + std::ptrdiff_t changedsize = std::max(zero, newallocatedmem - deallocatedmem); + //std::ptrdiff_t bomemoryrequiredbymesh = bufferObjectsMemoryRequired(_currallocatedboatt) - deallocatedmem + newallocatedmem; + unsigned int ii = 0; + for (typename std::vector::iterator it = _bo.begin(); it != _bo.end(); ++it) + { + INT_ATT_NAMES boname(ii); + //size_t sz = boExpectedSize(boname,replicated); + //size_t dim = boExpectedDimension(boname,replicated); - std::vector nv; //per vertex normal vector - if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTNORMAL]) - nv.resize(vertexchunk); + if (tobedeallocated[boname]) + bufferDeAllocationRequested(boname); + ++ii; + } - std::vector cv; // Per vertex color vector - if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTCOLOR]) - cv.resize(vertexchunk); + if (!_gpumeminfo.isAdditionalMemoryAvailable(changedsize)) + { + std::cout << "no additional memory available!!! memory required: " << changedsize << std::endl; + ii = 0; + for (typename std::vector::iterator it = _bo.begin(); it != _bo.end(); ++it) + { + INT_ATT_NAMES boname(ii); + size_t sz(boExpectedSize(boname, replicated)); + //there are already valid mesh attributes properly allocated in memory but there is not enough gpu memory for the remaining mesh. + //we have to deallocate the previously allocated mesh attributes + if ((*it != NULL) && ((sz == (*it)->_size))) + bufferDeAllocationRequested(boname); + ++ii; + } + _borendering = false; + return false; + } + else + { + bool failedallocation = false; + unsigned int ii = 0; + typename std::vector::iterator it = _bo.begin(); + while ((it != _bo.end()) && (!failedallocation)) + { + INT_ATT_NAMES boname(ii); + GLBufferObject* cbo = _bo[ii]; + if (tobeallocated[boname]) + { + cbo->_size = boExpectedSize(boname, replicated); + std::ptrdiff_t dim = boExpectedDimension(boname, replicated); + glGenBuffers(1, &cbo->_bohandle); + glBindBuffer(cbo->_target, cbo->_bohandle); + //we call glGetError BEFORE the glBufferData function in order to clean the error flag + GLenum err = glGetError(); + //assert(err == GL_NO_ERROR); + glBufferData(cbo->_target, dim, NULL, GL_STATIC_DRAW); + err = glGetError(); + //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 + failedallocation = (err == GL_OUT_OF_MEMORY) || (!_gpumeminfo.isAdditionalMemoryAvailable(dim)); + if (!failedallocation) + { + //setBufferPointerEnableClientState(boname); + setBufferPointer(boname); + _gpumeminfo.acquiredMemory(dim); + } + cbo->_isvalid = !failedallocation; + _borendering = !failedallocation; + glBindBuffer(cbo->_target, 0); + _currallocatedboatt[boname] = !failedallocation; + } + else + { + //the arity of the attribute contained in the bo didn't change so i can use the old space without reallocating it + if (cbo != NULL) + cbo->_isvalid = cbo->_isvalid || tobeupdated[boname]; + } + ++it; + ++ii; + } + if (failedallocation) + buffersDeAllocationRequested(_currallocatedboatt); + _borendering = !failedallocation; + } + return _borendering; + } - std::vector tv; // per vertex texture coord vector - if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTTEXTURE]) - tv.resize(vertexchunk * 2); + bool updateBuffersIndexedPipeline(const InternalRendAtts& attributestobeupdated) + { + _chunkmap.clear(); + size_t vn = _mesh.VN(); + size_t tn = _mesh.FN(); - size_t chunkingpu = 0; + size_t facechunk = std::min(size_t(tn), _perbatchprim); + size_t vertexchunk = std::min(size_t(vn), _perbatchprim); - for(size_t i=0;i pv; //position vector + if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTPOSITION]) + pv.resize(vertexchunk); - if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTNORMAL]) - { - nv[chunkindex].Import(_mesh.vert[i].cN()); - nv[chunkindex].Normalize(); - } + std::vector nv; //per vertex normal vector + if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTNORMAL]) + nv.resize(vertexchunk); - if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTCOLOR]) - { - cv[chunkindex] = _mesh.vert[i].cC(); - } - if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTTEXTURE]) - { - tv[chunkindex*2+0] = _mesh.vert[i].cT().U(); - tv[chunkindex*2+1] = _mesh.vert[i].cT().V(); - } + std::vector cv; // Per vertex color vector + if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTCOLOR]) + cv.resize(vertexchunk); - if((i == vn - 1) || (chunkindex == vertexchunk - 1)) - { - size_t chunksize = vertexchunk; - if (i == vn - 1) - chunksize = chunkindex + 1; + std::vector tv; // per vertex texture coord vector + if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTTEXTURE]) + tv.resize(vertexchunk * 2); - if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTPOSITION]) - { - GLBufferObject* buffobj = _bo[INT_ATT_NAMES::ATT_VERTPOSITION]; - glBindBuffer(GL_ARRAY_BUFFER, buffobj->_bohandle); - glBufferSubData(GL_ARRAY_BUFFER,chunkingpu * vertexchunk * buffobj->_components * buffobj->getSizeOfGLType(),buffobj->_components * buffobj->getSizeOfGLType() * chunksize,&pv[0]); - //std::vector tmppv; //position vector - //if (attributestobeupdated[GLMeshAttributesInfo::ATT_VERTPOSITION]) - // tmppv.resize(vertexchunk); - //glGetBufferSubData(GL_ARRAY_BUFFER,0,buffobj->_components * buffobj->getSizeOfGLType() * chunksize,&tmppv[0]); - glBindBuffer(GL_ARRAY_BUFFER, 0); + size_t chunkingpu = 0; - } - if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTNORMAL]) - { - GLBufferObject* buffobj = _bo[INT_ATT_NAMES::ATT_VERTNORMAL]; - glBindBuffer(GL_ARRAY_BUFFER, buffobj->_bohandle); - glBufferSubData(GL_ARRAY_BUFFER,chunkingpu * vertexchunk * buffobj->_components * buffobj->getSizeOfGLType(),buffobj->_components * buffobj->getSizeOfGLType() * chunksize,&nv[0]); - glBindBuffer(GL_ARRAY_BUFFER, 0); - } - if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTCOLOR]) - { - GLBufferObject* buffobj = _bo[INT_ATT_NAMES::ATT_VERTCOLOR]; - glBindBuffer(GL_ARRAY_BUFFER, buffobj->_bohandle); - glBufferSubData(GL_ARRAY_BUFFER,chunkingpu * vertexchunk * buffobj->_components * buffobj->getSizeOfGLType(),buffobj->_components * buffobj->getSizeOfGLType() * chunksize,&cv[0]); - glBindBuffer(GL_ARRAY_BUFFER, 0); - } - if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTTEXTURE]) - { - GLBufferObject* buffobj = _bo[INT_ATT_NAMES::ATT_VERTTEXTURE]; - glBindBuffer(GL_ARRAY_BUFFER, buffobj->_bohandle); - glBufferSubData(GL_ARRAY_BUFFER,chunkingpu * vertexchunk * buffobj->_components * buffobj->getSizeOfGLType(),buffobj->_components * buffobj->getSizeOfGLType() * chunksize,&tv[0]); - glBindBuffer(GL_ARRAY_BUFFER, 0); - } - glFinish(); - ++chunkingpu; - } - } + for (size_t i = 0; i < vn; ++i) + { + size_t chunkindex = i % vertexchunk; + if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTPOSITION]) + pv[chunkindex].Import(_mesh.vert[i].cP()); - pv.clear(); - nv.clear(); - cv.clear(); - tv.clear(); + if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTNORMAL]) + { + nv[chunkindex].Import(_mesh.vert[i].cN()); + nv[chunkindex].Normalize(); + } - chunkingpu = 0; - std::vector ti(facechunk * 3); - for(size_t i=0;i_bohandle); + glBufferSubData(GL_ARRAY_BUFFER, chunkingpu * vertexchunk * buffobj->_components * buffobj->getSizeOfGLType(), buffobj->_components * buffobj->getSizeOfGLType() * chunksize, &pv[0]); + //std::vector tmppv; //position vector + //if (attributestobeupdated[GLMeshAttributesInfo::ATT_VERTPOSITION]) + // tmppv.resize(vertexchunk); + //glGetBufferSubData(GL_ARRAY_BUFFER,0,buffobj->_components * buffobj->getSizeOfGLType() * chunksize,&tmppv[0]); + glBindBuffer(GL_ARRAY_BUFFER, 0); - if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTINDICES]) - { - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _bo[INT_ATT_NAMES::ATT_VERTINDICES]->_bohandle); - glBufferSubData(GL_ELEMENT_ARRAY_BUFFER,chunkingpu * facechunk * _bo[INT_ATT_NAMES::ATT_VERTINDICES]->_components * _bo[INT_ATT_NAMES::ATT_VERTINDICES]->getSizeOfGLType(),_bo[INT_ATT_NAMES::ATT_VERTINDICES]->_components * _bo[INT_ATT_NAMES::ATT_VERTINDICES]->getSizeOfGLType() * chunksize,&ti[0]); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - } - ++chunkingpu; - } - } - if ((attributestobeupdated[INT_ATT_NAMES::ATT_EDGEINDICES]) && (_edge.size() > 0)) - { - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _bo[INT_ATT_NAMES::ATT_EDGEINDICES]->_bohandle); - glBufferSubData(GL_ELEMENT_ARRAY_BUFFER,0,_bo[INT_ATT_NAMES::ATT_EDGEINDICES]->_components * _edge.size() * _bo[INT_ATT_NAMES::ATT_EDGEINDICES]->getSizeOfGLType(),&_edge[0]); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - } - return true; - } + } + if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTNORMAL]) + { + GLBufferObject* buffobj = _bo[INT_ATT_NAMES::ATT_VERTNORMAL]; + glBindBuffer(GL_ARRAY_BUFFER, buffobj->_bohandle); + glBufferSubData(GL_ARRAY_BUFFER, chunkingpu * vertexchunk * buffobj->_components * buffobj->getSizeOfGLType(), buffobj->_components * buffobj->getSizeOfGLType() * chunksize, &nv[0]); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } + if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTCOLOR]) + { + GLBufferObject* buffobj = _bo[INT_ATT_NAMES::ATT_VERTCOLOR]; + glBindBuffer(GL_ARRAY_BUFFER, buffobj->_bohandle); + glBufferSubData(GL_ARRAY_BUFFER, chunkingpu * vertexchunk * buffobj->_components * buffobj->getSizeOfGLType(), buffobj->_components * buffobj->getSizeOfGLType() * chunksize, &cv[0]); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } + if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTTEXTURE]) + { + GLBufferObject* buffobj = _bo[INT_ATT_NAMES::ATT_VERTTEXTURE]; + glBindBuffer(GL_ARRAY_BUFFER, buffobj->_bohandle); + glBufferSubData(GL_ARRAY_BUFFER, chunkingpu * vertexchunk * buffobj->_components * buffobj->getSizeOfGLType(), buffobj->_components * buffobj->getSizeOfGLType() * chunksize, &tv[0]); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } + glFinish(); + ++chunkingpu; + } + } - bool isThereAReplicatedPipelineView() const - { - bool replicated = false; - for(typename ViewsMap::const_iterator it = _perviewreqatts.begin();it != _perviewreqatts.end();++it) - { - //There is a replicated pipeline only if the att[ATT_VERTPOSITION] is true, otherwise is a spurious replicated view - for(size_t pm = 0; pm < size_t(PR_ARITY);++pm) - replicated = replicated || (InternalRendAtts::replicatedPipelineNeeded(it->second._intatts[pm]) && (it->second._pmmask.test(pm))); - } - return replicated; - } + pv.clear(); + nv.clear(); + cv.clear(); + tv.clear(); - bool isThereAnEdgesView() const - { - bool isthereaquadview = false; - for(typename ViewsMap::const_iterator it = _perviewreqatts.begin();it != _perviewreqatts.end();++it) - isthereaquadview = (it->second._intatts[size_t(PR_WIREFRAME_EDGES)][INT_ATT_NAMES::ATT_VERTPOSITION]) || isthereaquadview; + chunkingpu = 0; + std::vector ti(facechunk * 3); + for (size_t i = 0; i < tn; ++i) + { + size_t chunkindex = i % facechunk; + + ti[chunkindex * 3 + 0] = GLuint(vcg::tri::Index(_mesh, _mesh.face[i].V(0))); + ti[chunkindex * 3 + 1] = GLuint(vcg::tri::Index(_mesh, _mesh.face[i].V(1))); + ti[chunkindex * 3 + 2] = GLuint(vcg::tri::Index(_mesh, _mesh.face[i].V(2))); + + if ((i == tn - 1) || (chunkindex == facechunk - 1)) + { + size_t chunksize = facechunk; + if (i == tn - 1) + chunksize = chunkindex + 1; + + if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTINDICES]) + { + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _bo[INT_ATT_NAMES::ATT_VERTINDICES]->_bohandle); + glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, chunkingpu * facechunk * _bo[INT_ATT_NAMES::ATT_VERTINDICES]->_components * _bo[INT_ATT_NAMES::ATT_VERTINDICES]->getSizeOfGLType(), _bo[INT_ATT_NAMES::ATT_VERTINDICES]->_components * _bo[INT_ATT_NAMES::ATT_VERTINDICES]->getSizeOfGLType() * chunksize, &ti[0]); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + } + ++chunkingpu; + } + } + if ((attributestobeupdated[INT_ATT_NAMES::ATT_EDGEINDICES]) && (_edge.size() > 0)) + { + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _bo[INT_ATT_NAMES::ATT_EDGEINDICES]->_bohandle); + glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, _bo[INT_ATT_NAMES::ATT_EDGEINDICES]->_components * _edge.size() * _bo[INT_ATT_NAMES::ATT_EDGEINDICES]->getSizeOfGLType(), &_edge[0]); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + } + return true; + } + + bool isThereAReplicatedPipelineView() const + { + bool replicated = false; + for (typename ViewsMap::const_iterator it = _perviewreqatts.begin(); it != _perviewreqatts.end(); ++it) + { + //There is a replicated pipeline only if the att[ATT_VERTPOSITION] is true, otherwise is a spurious replicated view + for (size_t pm = 0; pm < size_t(PR_ARITY); ++pm) + replicated = replicated || (InternalRendAtts::replicatedPipelineNeeded(it->second._intatts[pm]) && (it->second._pmmask.test(pm))); + } + return replicated; + } + + bool isThereAnEdgesView() const + { + bool isthereaquadview = false; + for (typename ViewsMap::const_iterator it = _perviewreqatts.begin(); it != _perviewreqatts.end(); ++it) + isthereaquadview = (it->second._intatts[size_t(PR_WIREFRAME_EDGES)][INT_ATT_NAMES::ATT_VERTPOSITION]) || isthereaquadview; return isthereaquadview; - } + } - bool updateBuffersReplicatedPipeline(const InternalRendAtts& attributestobeupdated) - { - size_t tn = _mesh.fn; + bool updateBuffersReplicatedPipeline(const InternalRendAtts& attributestobeupdated) + { + size_t tn = _mesh.fn; - size_t facechunk = std::min(size_t(tn),_perbatchprim); + size_t facechunk = std::min(size_t(tn), _perbatchprim); - std::vector rpv; //position vector - if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTPOSITION]) - rpv.resize(facechunk * 3); + std::vector rpv; //position vector + if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTPOSITION]) + rpv.resize(facechunk * 3); - std::vector rnv; //per vertex normal vector - if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTNORMAL]) - rnv.resize(facechunk * 3); + std::vector rnv; //per vertex normal vector + if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTNORMAL]) + rnv.resize(facechunk * 3); - std::vector rfnv; //per face normal vector - if (attributestobeupdated[INT_ATT_NAMES::ATT_FACENORMAL]) - rfnv.resize(facechunk * 3); + std::vector rfnv; //per face normal vector + if (attributestobeupdated[INT_ATT_NAMES::ATT_FACENORMAL]) + rfnv.resize(facechunk * 3); - std::vector rcv; // Per vertex color vector - if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTCOLOR]) - rcv.resize(facechunk * 3); + std::vector rcv; // Per vertex color vector + if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTCOLOR]) + rcv.resize(facechunk * 3); - std::vector rfcv; // Per vertex color vector - if (attributestobeupdated[INT_ATT_NAMES::ATT_FACECOLOR]) - rfcv.resize(facechunk * 3); + std::vector rfcv; // Per vertex color vector + if (attributestobeupdated[INT_ATT_NAMES::ATT_FACECOLOR]) + rfcv.resize(facechunk * 3); - std::vector rtv; // per vertex texture coord vector - if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTTEXTURE]) - rtv.resize(facechunk * 3 * 2); + std::vector rtv; // per vertex texture coord vector + if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTTEXTURE]) + rtv.resize(facechunk * 3 * 2); - std::vector rwtv; // per wedge texture coord vector - if (attributestobeupdated[INT_ATT_NAMES::ATT_WEDGETEXTURE]) - rwtv.resize(facechunk * 3 * 2); + std::vector rwtv; // per wedge texture coord vector + if (attributestobeupdated[INT_ATT_NAMES::ATT_WEDGETEXTURE]) + rwtv.resize(facechunk * 3 * 2); - size_t chunkingpu = 0; + size_t chunkingpu = 0; - //it's a map containing for each texture seams n a vector of all the triangle index ranges having n has texture seam - //Suppose that in a mesh we have - //TXS_0{t0,t1,t2,t3}, TXS_4{t4,t5},TXS_0{t6},TXS_-1{t7,t8,t9},TXS_4{t10,t11} - //so chunkMap will contain - // -1 -> [] - // 0 -> [,] - // 4 -> [,] - // - //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 + //it's a map containing for each texture seams n a vector of all the triangle index ranges having n has texture seam + //Suppose that in a mesh we have + //TXS_0{t0,t1,t2,t3}, TXS_4{t4,t5},TXS_0{t6},TXS_-1{t7,t8,t9},TXS_4{t10,t11} + //so chunkMap will contain + // -1 -> [] + // 0 -> [,] + // 4 -> [,] + // + //if the map has no-texture coords at all in order to unify the code we fill the ChunkMap with texture seam -1 and a single triangle range going from face_0 to face_n-1 - if (attributestobeupdated[INT_ATT_NAMES::ATT_WEDGETEXTURE] || attributestobeupdated[INT_ATT_NAMES::ATT_VERTTEXTURE]) - { - _chunkmap.clear(); - if (attributestobeupdated[INT_ATT_NAMES::ATT_WEDGETEXTURE]) - fillchunkMap(); - else - if(attributestobeupdated[INT_ATT_NAMES::ATT_VERTTEXTURE]) - _chunkmap[0].push_back(std::make_pair(0,tn-1)); - } + if (attributestobeupdated[INT_ATT_NAMES::ATT_WEDGETEXTURE] || attributestobeupdated[INT_ATT_NAMES::ATT_VERTTEXTURE]) + { + _chunkmap.clear(); + if (attributestobeupdated[INT_ATT_NAMES::ATT_WEDGETEXTURE]) + fillchunkMap(); + else + if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTTEXTURE]) + _chunkmap[0].push_back(std::make_pair(0, tn - 1)); + } - //default case: no texture is required to be rendered but a non texture attribute has to be updated - //we have to init the _chunkmap with just one entry (-1...that means no texture) referring all the triangles in the mesh - if ((!_currallocatedboatt[INT_ATT_NAMES::ATT_VERTTEXTURE] && !_currallocatedboatt[INT_ATT_NAMES::ATT_WEDGETEXTURE]) && - (attributestobeupdated[INT_ATT_NAMES::ATT_VERTPOSITION] || - attributestobeupdated[INT_ATT_NAMES::ATT_VERTNORMAL] || attributestobeupdated[INT_ATT_NAMES::ATT_FACENORMAL] || - attributestobeupdated[INT_ATT_NAMES::ATT_VERTCOLOR] || attributestobeupdated[INT_ATT_NAMES::ATT_FACECOLOR])) - { - _chunkmap.clear(); - _chunkmap[-1].push_back(std::make_pair(0,tn-1)); - } + //default case: no texture is required to be rendered but a non texture attribute has to be updated + //we have to init the _chunkmap with just one entry (-1...that means no texture) referring all the triangles in the mesh + if ((!_currallocatedboatt[INT_ATT_NAMES::ATT_VERTTEXTURE] && !_currallocatedboatt[INT_ATT_NAMES::ATT_WEDGETEXTURE]) && + (attributestobeupdated[INT_ATT_NAMES::ATT_VERTPOSITION] || + attributestobeupdated[INT_ATT_NAMES::ATT_VERTNORMAL] || attributestobeupdated[INT_ATT_NAMES::ATT_FACENORMAL] || + attributestobeupdated[INT_ATT_NAMES::ATT_VERTCOLOR] || attributestobeupdated[INT_ATT_NAMES::ATT_FACECOLOR])) + { + _chunkmap.clear(); + _chunkmap[-1].push_back(std::make_pair(0, tn - 1)); + } - int t = 0; - if (attributestobeupdated[INT_ATT_NAMES::ATT_WEDGETEXTURE] || attributestobeupdated[INT_ATT_NAMES::ATT_VERTTEXTURE]) - { - _texindnumtriangles.clear(); - _texindnumtriangles.resize(_chunkmap.size()); - } - - std::vector vpatlas; - if (attributestobeupdated[INT_ATT_NAMES::ATT_EDGEINDICES]) - vpatlas.resize(_mesh.VN(),UINT_MAX); + int t = 0; + if (attributestobeupdated[INT_ATT_NAMES::ATT_WEDGETEXTURE] || attributestobeupdated[INT_ATT_NAMES::ATT_VERTTEXTURE]) + { + _texindnumtriangles.clear(); + _texindnumtriangles.resize(_chunkmap.size()); + } - int faceind = 0; - size_t chunkindex = faceind; + std::vector vpatlas; + if (attributestobeupdated[INT_ATT_NAMES::ATT_EDGEINDICES]) + vpatlas.resize(_mesh.VN(), UINT_MAX); + + int faceind = 0; + size_t chunkindex = faceind; GLuint triangles = 0; - for(ChunkMap::const_iterator mit = _chunkmap.begin();mit != _chunkmap.end();++mit) - { - for (ChunkVector::const_iterator cit = mit->second.begin();cit != mit->second.end();++cit) - { - for(size_t indf = cit->first;indf<=cit->second;++indf) - { - chunkindex = faceind % facechunk; - if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTPOSITION]) - { - rpv[chunkindex*3+0].Import(_mesh.face[indf].V(0)->P()); - rpv[chunkindex*3+1].Import(_mesh.face[indf].V(1)->P()); - rpv[chunkindex*3+2].Import(_mesh.face[indf].V(2)->P()); - } - if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTNORMAL]) - { - rnv[chunkindex*3+0].Import(_mesh.face[indf].V(0)->N().Normalize()); - rnv[chunkindex*3+1].Import(_mesh.face[indf].V(1)->N().Normalize()); - rnv[chunkindex*3+2].Import(_mesh.face[indf].V(2)->N().Normalize()); - } + for (ChunkMap::const_iterator mit = _chunkmap.begin(); mit != _chunkmap.end(); ++mit) + { + for (ChunkVector::const_iterator cit = mit->second.begin(); cit != mit->second.end(); ++cit) + { + for (size_t indf = cit->first; indf <= cit->second; ++indf) + { + chunkindex = faceind % facechunk; + if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTPOSITION]) + { + rpv[chunkindex * 3 + 0].Import(_mesh.face[indf].V(0)->P()); + rpv[chunkindex * 3 + 1].Import(_mesh.face[indf].V(1)->P()); + rpv[chunkindex * 3 + 2].Import(_mesh.face[indf].V(2)->P()); + } + if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTNORMAL]) + { + rnv[chunkindex * 3 + 0].Import(_mesh.face[indf].V(0)->N().Normalize()); + rnv[chunkindex * 3 + 1].Import(_mesh.face[indf].V(1)->N().Normalize()); + rnv[chunkindex * 3 + 2].Import(_mesh.face[indf].V(2)->N().Normalize()); + } - if (attributestobeupdated[INT_ATT_NAMES::ATT_FACENORMAL]) - { - rfnv[chunkindex*3+0].Import(_mesh.face[indf].N().Normalize()); - rfnv[chunkindex*3+1].Import(_mesh.face[indf].N().Normalize()); - rfnv[chunkindex*3+2].Import(_mesh.face[indf].N().Normalize()); - } + if (attributestobeupdated[INT_ATT_NAMES::ATT_FACENORMAL]) + { + rfnv[chunkindex * 3 + 0].Import(_mesh.face[indf].N().Normalize()); + rfnv[chunkindex * 3 + 1].Import(_mesh.face[indf].N().Normalize()); + rfnv[chunkindex * 3 + 2].Import(_mesh.face[indf].N().Normalize()); + } - if ((attributestobeupdated[INT_ATT_NAMES::ATT_VERTCOLOR])) - { - rcv[chunkindex*3+0] = _mesh.face[indf].V(0)->C(); - rcv[chunkindex*3+1] = _mesh.face[indf].V(1)->C(); - rcv[chunkindex*3+2] = _mesh.face[indf].V(2)->C(); - } + if ((attributestobeupdated[INT_ATT_NAMES::ATT_VERTCOLOR])) + { + rcv[chunkindex * 3 + 0] = _mesh.face[indf].V(0)->C(); + rcv[chunkindex * 3 + 1] = _mesh.face[indf].V(1)->C(); + rcv[chunkindex * 3 + 2] = _mesh.face[indf].V(2)->C(); + } - if ((attributestobeupdated[INT_ATT_NAMES::ATT_FACECOLOR])) - { - rfcv[chunkindex*3+0] = _mesh.face[indf].C(); - rfcv[chunkindex*3+1] = _mesh.face[indf].C(); - rfcv[chunkindex*3+2] = _mesh.face[indf].C(); - } + if ((attributestobeupdated[INT_ATT_NAMES::ATT_FACECOLOR])) + { + rfcv[chunkindex * 3 + 0] = _mesh.face[indf].C(); + rfcv[chunkindex * 3 + 1] = _mesh.face[indf].C(); + rfcv[chunkindex * 3 + 2] = _mesh.face[indf].C(); + } - if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTTEXTURE]) - { - rtv[chunkindex*6+0]=float(_mesh.face[indf].V(0)->T().U()); - rtv[chunkindex*6+1]=float(_mesh.face[indf].V(0)->T().V()); - rtv[chunkindex*6+2]=float(_mesh.face[indf].V(1)->T().U()); - rtv[chunkindex*6+3]=float(_mesh.face[indf].V(1)->T().V()); - rtv[chunkindex*6+4]=float(_mesh.face[indf].V(2)->T().U()); - rtv[chunkindex*6+5]=float(_mesh.face[indf].V(2)->T().V()); - } + if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTTEXTURE]) + { + rtv[chunkindex * 6 + 0] = float(_mesh.face[indf].V(0)->T().U()); + rtv[chunkindex * 6 + 1] = float(_mesh.face[indf].V(0)->T().V()); + rtv[chunkindex * 6 + 2] = float(_mesh.face[indf].V(1)->T().U()); + rtv[chunkindex * 6 + 3] = float(_mesh.face[indf].V(1)->T().V()); + rtv[chunkindex * 6 + 4] = float(_mesh.face[indf].V(2)->T().U()); + rtv[chunkindex * 6 + 5] = float(_mesh.face[indf].V(2)->T().V()); + } - if (attributestobeupdated[INT_ATT_NAMES::ATT_WEDGETEXTURE]) - { - rwtv[chunkindex*6+0]=float(_mesh.face[indf].WT(0).U()); - rwtv[chunkindex*6+1]=float(_mesh.face[indf].WT(0).V()); - rwtv[chunkindex*6+2]=float(_mesh.face[indf].WT(1).U()); - rwtv[chunkindex*6+3]=float(_mesh.face[indf].WT(1).V()); - rwtv[chunkindex*6+4]=float(_mesh.face[indf].WT(2).U()); - rwtv[chunkindex*6+5]=float(_mesh.face[indf].WT(2).V()); - } + if (attributestobeupdated[INT_ATT_NAMES::ATT_WEDGETEXTURE]) + { + rwtv[chunkindex * 6 + 0] = float(_mesh.face[indf].WT(0).U()); + rwtv[chunkindex * 6 + 1] = float(_mesh.face[indf].WT(0).V()); + rwtv[chunkindex * 6 + 2] = float(_mesh.face[indf].WT(1).U()); + rwtv[chunkindex * 6 + 3] = float(_mesh.face[indf].WT(1).V()); + rwtv[chunkindex * 6 + 4] = float(_mesh.face[indf].WT(2).U()); + rwtv[chunkindex * 6 + 5] = float(_mesh.face[indf].WT(2).V()); + } - if (attributestobeupdated[INT_ATT_NAMES::ATT_EDGEINDICES]) - { - for (int ii = 0;ii < 3;++ii) - { - size_t v = vcg::tri::Index(_mesh,_mesh.face[indf].V(ii)); - if (vpatlas[v] == UINT_MAX) - vpatlas[v] = faceind*3+ii; - } - } + if (attributestobeupdated[INT_ATT_NAMES::ATT_EDGEINDICES]) + { + for (int ii = 0; ii < 3; ++ii) + { + size_t v = vcg::tri::Index(_mesh, _mesh.face[indf].V(ii)); + if (vpatlas[v] == UINT_MAX) + vpatlas[v] = faceind * 3 + ii; + } + } - if((faceind == tn - 1) || (chunkindex == facechunk - 1)) - { - size_t chunksize = facechunk; - if (faceind == tn - 1) - chunksize = chunkindex + 1; + if ((faceind == tn - 1) || (chunkindex == facechunk - 1)) + { + size_t chunksize = facechunk; + if (faceind == tn - 1) + chunksize = chunkindex + 1; - if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTPOSITION]) - { - GLBufferObject* buffobj = _bo[INT_ATT_NAMES::ATT_VERTPOSITION]; - glBindBuffer(GL_ARRAY_BUFFER, buffobj->_bohandle); - glBufferSubData(GL_ARRAY_BUFFER,chunkingpu * facechunk * 3 * buffobj->_components * buffobj->getSizeOfGLType(),3 * buffobj->_components * buffobj->getSizeOfGLType() * chunksize,&rpv[0]); - glBindBuffer(GL_ARRAY_BUFFER, 0); - } + if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTPOSITION]) + { + GLBufferObject* buffobj = _bo[INT_ATT_NAMES::ATT_VERTPOSITION]; + glBindBuffer(GL_ARRAY_BUFFER, buffobj->_bohandle); + glBufferSubData(GL_ARRAY_BUFFER, chunkingpu * facechunk * 3 * buffobj->_components * buffobj->getSizeOfGLType(), 3 * buffobj->_components * buffobj->getSizeOfGLType() * chunksize, &rpv[0]); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } - if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTNORMAL]) - { - GLBufferObject* buffobj = _bo[INT_ATT_NAMES::ATT_VERTNORMAL]; - glBindBuffer(GL_ARRAY_BUFFER, buffobj->_bohandle); - glBufferSubData(GL_ARRAY_BUFFER,chunkingpu * facechunk * 3 * buffobj->_components * buffobj->getSizeOfGLType(),3 * buffobj->_components * buffobj->getSizeOfGLType() * chunksize,&rnv[0]); - glBindBuffer(GL_ARRAY_BUFFER, 0); - } + if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTNORMAL]) + { + GLBufferObject* buffobj = _bo[INT_ATT_NAMES::ATT_VERTNORMAL]; + glBindBuffer(GL_ARRAY_BUFFER, buffobj->_bohandle); + glBufferSubData(GL_ARRAY_BUFFER, chunkingpu * facechunk * 3 * buffobj->_components * buffobj->getSizeOfGLType(), 3 * buffobj->_components * buffobj->getSizeOfGLType() * chunksize, &rnv[0]); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } - if (attributestobeupdated[INT_ATT_NAMES::ATT_FACENORMAL]) - { - GLBufferObject* buffobj = _bo[INT_ATT_NAMES::ATT_FACENORMAL]; - glBindBuffer(GL_ARRAY_BUFFER, buffobj->_bohandle); - glBufferSubData(GL_ARRAY_BUFFER,chunkingpu * facechunk * 3 * buffobj->_components * buffobj->getSizeOfGLType(),3 * buffobj->_components * buffobj->getSizeOfGLType() * chunksize,&rfnv[0]); - glBindBuffer(GL_ARRAY_BUFFER, 0); - } + if (attributestobeupdated[INT_ATT_NAMES::ATT_FACENORMAL]) + { + GLBufferObject* buffobj = _bo[INT_ATT_NAMES::ATT_FACENORMAL]; + glBindBuffer(GL_ARRAY_BUFFER, buffobj->_bohandle); + glBufferSubData(GL_ARRAY_BUFFER, chunkingpu * facechunk * 3 * buffobj->_components * buffobj->getSizeOfGLType(), 3 * buffobj->_components * buffobj->getSizeOfGLType() * chunksize, &rfnv[0]); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } - if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTCOLOR]) - { - GLBufferObject* buffobj = _bo[INT_ATT_NAMES::ATT_VERTCOLOR]; - glBindBuffer(GL_ARRAY_BUFFER, buffobj->_bohandle); - glBufferSubData(GL_ARRAY_BUFFER,chunkingpu * facechunk * 3 *buffobj->_components * buffobj->getSizeOfGLType(),3 * buffobj->_components * buffobj->getSizeOfGLType() * chunksize,&rcv[0]); - glBindBuffer(GL_ARRAY_BUFFER, 0); - } + if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTCOLOR]) + { + GLBufferObject* buffobj = _bo[INT_ATT_NAMES::ATT_VERTCOLOR]; + glBindBuffer(GL_ARRAY_BUFFER, buffobj->_bohandle); + glBufferSubData(GL_ARRAY_BUFFER, chunkingpu * facechunk * 3 * buffobj->_components * buffobj->getSizeOfGLType(), 3 * buffobj->_components * buffobj->getSizeOfGLType() * chunksize, &rcv[0]); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } - if (attributestobeupdated[INT_ATT_NAMES::ATT_FACECOLOR]) - { - GLBufferObject* buffobj = _bo[INT_ATT_NAMES::ATT_FACECOLOR]; - glBindBuffer(GL_ARRAY_BUFFER, buffobj->_bohandle); - glBufferSubData(GL_ARRAY_BUFFER,chunkingpu * facechunk * 3 *buffobj->_components * buffobj->getSizeOfGLType(),3 * buffobj->_components * buffobj->getSizeOfGLType() * chunksize,&rfcv[0]); - glBindBuffer(GL_ARRAY_BUFFER, 0); - } + if (attributestobeupdated[INT_ATT_NAMES::ATT_FACECOLOR]) + { + GLBufferObject* buffobj = _bo[INT_ATT_NAMES::ATT_FACECOLOR]; + glBindBuffer(GL_ARRAY_BUFFER, buffobj->_bohandle); + glBufferSubData(GL_ARRAY_BUFFER, chunkingpu * facechunk * 3 * buffobj->_components * buffobj->getSizeOfGLType(), 3 * buffobj->_components * buffobj->getSizeOfGLType() * chunksize, &rfcv[0]); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } - if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTTEXTURE]) - { - GLBufferObject* buffobj = _bo[INT_ATT_NAMES::ATT_VERTTEXTURE]; - glBindBuffer(GL_ARRAY_BUFFER, buffobj->_bohandle); - glBufferSubData(GL_ARRAY_BUFFER,chunkingpu * facechunk * 3 *buffobj->_components * buffobj->getSizeOfGLType(),3 * buffobj->_components * buffobj->getSizeOfGLType() * chunksize,&rtv[0]); - glBindBuffer(GL_ARRAY_BUFFER, 0); - } + if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTTEXTURE]) + { + GLBufferObject* buffobj = _bo[INT_ATT_NAMES::ATT_VERTTEXTURE]; + glBindBuffer(GL_ARRAY_BUFFER, buffobj->_bohandle); + glBufferSubData(GL_ARRAY_BUFFER, chunkingpu * facechunk * 3 * buffobj->_components * buffobj->getSizeOfGLType(), 3 * buffobj->_components * buffobj->getSizeOfGLType() * chunksize, &rtv[0]); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } - if (attributestobeupdated[INT_ATT_NAMES::ATT_WEDGETEXTURE]) - { - GLBufferObject* buffobj = _bo[INT_ATT_NAMES::ATT_WEDGETEXTURE]; - glBindBuffer(GL_ARRAY_BUFFER, buffobj->_bohandle); - glBufferSubData(GL_ARRAY_BUFFER,chunkingpu * facechunk * 3 *buffobj->_components * buffobj->getSizeOfGLType(),3 * buffobj->_components * buffobj->getSizeOfGLType() * chunksize,&rwtv[0]); - glBindBuffer(GL_ARRAY_BUFFER, 0); - } + if (attributestobeupdated[INT_ATT_NAMES::ATT_WEDGETEXTURE]) + { + GLBufferObject* buffobj = _bo[INT_ATT_NAMES::ATT_WEDGETEXTURE]; + glBindBuffer(GL_ARRAY_BUFFER, buffobj->_bohandle); + glBufferSubData(GL_ARRAY_BUFFER, chunkingpu * facechunk * 3 * buffobj->_components * buffobj->getSizeOfGLType(), 3 * buffobj->_components * buffobj->getSizeOfGLType() * chunksize, &rwtv[0]); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } - ++chunkingpu; - } - ++faceind; - } - triangles += cit->second - cit->first + 1; - } + ++chunkingpu; + } + ++faceind; + } + triangles += cit->second - cit->first + 1; + } - if ((attributestobeupdated[INT_ATT_NAMES::ATT_EDGEINDICES]) && (_edge.size() > 0)) - { - for(typename std::vector::iterator it = _edge.begin();it != _edge.end();++it) - { - it->_v[0] = vpatlas[it->_v[0]]; - it->_v[1] = vpatlas[it->_v[1]]; - } + if ((attributestobeupdated[INT_ATT_NAMES::ATT_EDGEINDICES]) && (_edge.size() > 0)) + { + for (typename std::vector::iterator it = _edge.begin(); it != _edge.end(); ++it) + { + it->_v[0] = vpatlas[it->_v[0]]; + it->_v[1] = vpatlas[it->_v[1]]; + } - GLBufferObject* buffobj = _bo[INT_ATT_NAMES::ATT_EDGEINDICES]; - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffobj->_bohandle); - glBufferSubData(GL_ELEMENT_ARRAY_BUFFER,0,buffobj->_components * buffobj->getSizeOfGLType() * _edge.size(),&_edge[0]); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - } + GLBufferObject* buffobj = _bo[INT_ATT_NAMES::ATT_EDGEINDICES]; + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffobj->_bohandle); + glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, buffobj->_components * buffobj->getSizeOfGLType() * _edge.size(), &_edge[0]); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + } - if (attributestobeupdated[INT_ATT_NAMES::ATT_WEDGETEXTURE] || attributestobeupdated[INT_ATT_NAMES::ATT_VERTTEXTURE]) - _texindnumtriangles[t] = std::make_pair(mit->first,triangles); - ++t; - } + if (attributestobeupdated[INT_ATT_NAMES::ATT_WEDGETEXTURE] || attributestobeupdated[INT_ATT_NAMES::ATT_VERTTEXTURE]) + _texindnumtriangles[t] = std::make_pair(mit->first, triangles); + ++t; + } - //return (k != tn) - // throw MeshLabException("Mesh has not been properly partitioned"); - return true; - } + //return (k != tn) + // throw MeshLabException("Mesh has not been properly partitioned"); + return true; + } - void buffersDeAllocationRequested(const InternalRendAtts& rq) - { - for(unsigned int ii = 0;ii < INT_ATT_NAMES::enumArity();++ii) - { - INT_ATT_NAMES boname(ii); - if ((_bo[ii] != NULL) && (rq[boname])) - bufferDeAllocationRequested(boname); - } - } + void buffersDeAllocationRequested(const InternalRendAtts& rq) + { + for (unsigned int ii = 0; ii < INT_ATT_NAMES::enumArity(); ++ii) + { + INT_ATT_NAMES boname(ii); + if ((_bo[ii] != NULL) && (rq[boname])) + bufferDeAllocationRequested(boname); + } + } - void bufferDeAllocationRequested(INT_ATT_NAMES att) - { - unsigned int ind(att); - if ((ind < 0) || (ind >= (unsigned int) _bo.size())) - return; - GLBufferObject* bobj = _bo[ind]; - if (bobj == NULL) - return; + void bufferDeAllocationRequested(INT_ATT_NAMES att) + { + unsigned int ind(att); + if ((ind < 0) || (ind >= (unsigned int)_bo.size())) + return; + GLBufferObject* bobj = _bo[ind]; + if (bobj == NULL) + return; - if ((att != INT_ATT_NAMES::ATT_VERTINDICES) && (att != INT_ATT_NAMES::ATT_EDGEINDICES) /*&& (att != INT_ATT_NAMES::ATT_FIXEDCOLOR)*/) - { - glDisableClientState(bobj->_clientstatetag); - } + if ((att != INT_ATT_NAMES::ATT_VERTINDICES) && (att != INT_ATT_NAMES::ATT_EDGEINDICES) /*&& (att != INT_ATT_NAMES::ATT_FIXEDCOLOR)*/) + { + glDisableClientState(bobj->_clientstatetag); + } //glBufferData(bobj->_target, sizeof(vcg::Point3f)*_primitivebatch, 0, GL_DYNAMIC_DRAW); - glDeleteBuffers(1,&(bobj->_bohandle)); - glFlush(); - glFinish(); + glDeleteBuffers(1, &(bobj->_bohandle)); + glFlush(); + glFinish(); - if (bobj->_size > 0) - //we don't use dim cause dim is the value that is going to be allocated, instead use (*it)->_size * (*it)->getSizeOfGLType() is the value already in the buffer - _gpumeminfo.releasedMemory(bobj->_size * bobj->getSizeOfGLType()); - bobj->_isvalid = false; - bobj->_size = 0; - _currallocatedboatt[att] = false; - } + if (bobj->_size > 0) + //we don't use dim cause dim is the value that is going to be allocated, instead use (*it)->_size * (*it)->getSizeOfGLType() is the value already in the buffer + _gpumeminfo.releasedMemory(bobj->_size * bobj->getSizeOfGLType()); + bobj->_isvalid = false; + bobj->_size = 0; + _currallocatedboatt[att] = false; + } - std::ptrdiff_t bufferObjectsMemoryRequired(const InternalRendAtts& rqatt) const - { - bool replicated = InternalRendAtts::replicatedPipelineNeeded(rqatt); - std::ptrdiff_t result(0); + std::ptrdiff_t bufferObjectsMemoryRequired(const InternalRendAtts& rqatt) const + { + bool replicated = InternalRendAtts::replicatedPipelineNeeded(rqatt); + std::ptrdiff_t result(0); - for(unsigned int ii = 0;ii < INT_ATT_NAMES::enumArity();++ii) - { - INT_ATT_NAMES nm(ii); - if (rqatt[nm]) - result += (std::ptrdiff_t) boExpectedDimension(nm,replicated); - } - return result; - } + for (unsigned int ii = 0; ii < INT_ATT_NAMES::enumArity(); ++ii) + { + INT_ATT_NAMES nm(ii); + if (rqatt[nm]) + result += (std::ptrdiff_t) boExpectedDimension(nm, replicated); + } + return result; + } - //expected number of cells should have the required bo - //generateindex is true when i have a triangle based mesh - // is false when i have a point based mesh - size_t boExpectedSize(INT_ATT_NAMES name,bool replicatedpipeline) const - { - try - { - - GLBufferObject& cbo = *_bo.at((unsigned int) name); - size_t vertnum(_mesh.VN()); - size_t facenum(_mesh.FN()); + //expected number of cells should have the required bo + //generateindex is true when i have a triangle based mesh + // is false when i have a point based mesh + size_t boExpectedSize(INT_ATT_NAMES name, bool replicatedpipeline) const + { + try + { - switch((unsigned int) name) - { - case(INT_ATT_NAMES::ATT_VERTPOSITION): - case(INT_ATT_NAMES::ATT_VERTNORMAL): - case(INT_ATT_NAMES::ATT_VERTCOLOR): - case(INT_ATT_NAMES::ATT_VERTTEXTURE): - { - if (replicatedpipeline) - return facenum * 3 * cbo._components; - else - return vertnum * cbo._components; - } + GLBufferObject& cbo = *_bo.at((unsigned int)name); + size_t vertnum(_mesh.VN()); + size_t facenum(_mesh.FN()); - case(INT_ATT_NAMES::ATT_FACENORMAL): - case(INT_ATT_NAMES::ATT_FACECOLOR): - case(INT_ATT_NAMES::ATT_WEDGETEXTURE): - { - if (replicatedpipeline) - return facenum * 3 * cbo._components; - else - return 0; - } - case(INT_ATT_NAMES::ATT_VERTINDICES): - { - if (replicatedpipeline) - return 0; - else - return facenum * cbo._components; - } - case(INT_ATT_NAMES::ATT_EDGEINDICES): - { - return _edge.size() * cbo._components; - } + switch ((unsigned int)name) + { + case(INT_ATT_NAMES::ATT_VERTPOSITION): + case(INT_ATT_NAMES::ATT_VERTNORMAL): + case(INT_ATT_NAMES::ATT_VERTCOLOR): + case(INT_ATT_NAMES::ATT_VERTTEXTURE): + { + if (replicatedpipeline) + return facenum * 3 * cbo._components; + else + return vertnum * cbo._components; + } - default : break; - } - } - catch(std::out_of_range& /*exc*/) - { - return 0; - } - return 0; - } + case(INT_ATT_NAMES::ATT_FACENORMAL): + case(INT_ATT_NAMES::ATT_FACECOLOR): + case(INT_ATT_NAMES::ATT_WEDGETEXTURE): + { + if (replicatedpipeline) + return facenum * 3 * cbo._components; + else + return 0; + } + case(INT_ATT_NAMES::ATT_VERTINDICES): + { + if (replicatedpipeline) + return 0; + else + return facenum * cbo._components; + } + case(INT_ATT_NAMES::ATT_EDGEINDICES): + { + return _edge.size() * cbo._components; + } - size_t boExpectedDimension(INT_ATT_NAMES name,bool replicatedpipeline) const - { - try - { - size_t sz = boExpectedSize(name,replicatedpipeline); - unsigned int ind = (unsigned int) name; - GLBufferObject* cbo = _bo.at(ind); - if (cbo == NULL) - return 0; - else - return sz * cbo->getSizeOfGLType(); - } - catch(std::out_of_range& /*exc*/) - { - return 0; - } - return 0; - } + default: break; + } + } + catch (std::out_of_range& /*exc*/) + { + return 0; + } + return 0; + } + + size_t boExpectedDimension(INT_ATT_NAMES name, bool replicatedpipeline) const + { + try + { + size_t sz = boExpectedSize(name, replicatedpipeline); + unsigned int ind = (unsigned int)name; + GLBufferObject* cbo = _bo.at(ind); + if (cbo == NULL) + return 0; + else + return sz * cbo->getSizeOfGLType(); + } + catch (std::out_of_range& /*exc*/) + { + return 0; + } + return 0; + } void drawFun(const PVData& dt, const std::vector& textid = std::vector()) const { @@ -1362,7 +1363,7 @@ namespace vcg glDisable(GL_POLYGON_OFFSET_FILL); } if (dt.isPrimitiveActive(PR_POINTS)) - drawPoints(dt._intatts[size_t(PR_POINTS)], dt._glopts,textid); + drawPoints(dt._intatts[size_t(PR_POINTS)], dt._glopts, textid); glPopMatrix(); glPopAttrib(); @@ -1370,293 +1371,293 @@ namespace vcg glFinish(); } - void drawFilledTriangles(const InternalRendAtts& req,const GL_OPTIONS_DERIVED_TYPE* glopts,const std::vector& textureindex = std::vector()) const - { - if (_mesh.VN() == 0) - return; + void drawFilledTriangles(const InternalRendAtts& req, const GL_OPTIONS_DERIVED_TYPE* glopts, const std::vector& textureindex = std::vector()) const + { + if (_mesh.VN() == 0) + return; - glPushAttrib(GL_ALL_ATTRIB_BITS); - - bool isgloptsvalid = (glopts != NULL); - - if (isgloptsvalid && glopts->_persolid_noshading) - glDisable(GL_LIGHTING); - else - if ((!isgloptsvalid) || (req[INT_ATT_NAMES::ATT_VERTNORMAL]) || (req[INT_ATT_NAMES::ATT_FACENORMAL])) - { - glEnable(GL_LIGHTING); - } + glPushAttrib(GL_ALL_ATTRIB_BITS); - glEnable(GL_COLOR_MATERIAL); - if ((isgloptsvalid) && (glopts->_persolid_fixed_color_enabled)) - glColor(glopts->_persolid_fixed_color); - else - { - if ((isgloptsvalid) && (glopts->_persolid_mesh_color_enabled)) - glColor(_mesh.C()); - else - { - if ((req[INT_ATT_NAMES::ATT_VERTCOLOR]) || (req[INT_ATT_NAMES::ATT_FACECOLOR])) - glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE); - else - glColor(vcg::Color4b(vcg::Color4b::LightGray)); - } - } + bool isgloptsvalid = (glopts != NULL); - if (isBORenderingAvailable()) - drawTrianglesBO(req,textureindex); - else - drawTrianglesIM(req,textureindex); + if (isgloptsvalid && glopts->_persolid_noshading) + glDisable(GL_LIGHTING); + else + if ((!isgloptsvalid) || (req[INT_ATT_NAMES::ATT_VERTNORMAL]) || (req[INT_ATT_NAMES::ATT_FACENORMAL])) + { + glEnable(GL_LIGHTING); + } - glPopAttrib(); - } + glEnable(GL_COLOR_MATERIAL); + if ((isgloptsvalid) && (glopts->_persolid_fixed_color_enabled)) + glColor(glopts->_persolid_fixed_color); + else + { + if ((isgloptsvalid) && (glopts->_persolid_mesh_color_enabled)) + glColor(_mesh.C()); + else + { + if ((req[INT_ATT_NAMES::ATT_VERTCOLOR]) || (req[INT_ATT_NAMES::ATT_FACECOLOR])) + glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); + else + glColor(vcg::Color4b(vcg::Color4b::LightGray)); + } + } + + if (isBORenderingAvailable()) + drawTrianglesBO(req, textureindex); + else + drawTrianglesIM(req, textureindex); + + glPopAttrib(); + } - void drawWiredTriangles(const InternalRendAtts& req,const GL_OPTIONS_DERIVED_TYPE* glopts,const std::vector& textureindex = std::vector()) const - { - if (_mesh.VN() == 0) - return; - glPushAttrib(GL_ALL_ATTRIB_BITS); - - - bool isgloptsvalid = (glopts != NULL); - - if (isgloptsvalid && glopts->_perwire_noshading) - glDisable(GL_LIGHTING); - else - if ((!isgloptsvalid) || (req[INT_ATT_NAMES::ATT_VERTNORMAL])) - { - glEnable(GL_LIGHTING); - } - - glEnable(GL_COLOR_MATERIAL); - if ((isgloptsvalid) && (glopts->_perwire_fixed_color_enabled)) - glColor(glopts->_perwire_fixed_color); - else - { - if ((isgloptsvalid) && (glopts->_perwire_mesh_color_enabled)) - glColor(_mesh.C()); - else - { - if (req[INT_ATT_NAMES::ATT_VERTCOLOR]) - glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE); - else - glColor(vcg::Color4b(vcg::Color4b::DarkGray)); - } - } - float linewidth = 1.0f; - if (isgloptsvalid) - linewidth = glopts->_perwire_wirewidth; - glLineWidth(linewidth); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - - if (isBORenderingAvailable()) - drawTrianglesBO(req,textureindex); - else - drawTrianglesIM(req,textureindex); - - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - glPopAttrib(); - } - - void drawTrianglesBO(const InternalRendAtts& req,const std::vector& textureindex = std::vector()) const - { - updateClientState(req); - - bool replicated = InternalRendAtts::replicatedPipelineNeeded(_currallocatedboatt); - - if (replicated) - { - //qDebug("Replicated drawing"); - int firsttriangleoffset = 0; - if(!req[INT_ATT_NAMES::ATT_VERTTEXTURE] && !req[INT_ATT_NAMES::ATT_WEDGETEXTURE]) - { - glDisable(GL_TEXTURE_2D); - glDrawArrays(GL_TRIANGLES,0,_mesh.fn * 3); - } - else - { - glEnable(GL_TEXTURE_2D); - for(std::vector< std::pair >::const_iterator it = _texindnumtriangles.begin();it != _texindnumtriangles.end();++it) - { - if ((it->first != -1) && (it->first < textureindex.size())) - glBindTexture(GL_TEXTURE_2D,textureindex[it->first]); - else - glBindTexture(GL_TEXTURE_2D,0); - glDrawArrays(GL_TRIANGLES,firsttriangleoffset,it->second * 3 - firsttriangleoffset); - firsttriangleoffset = it->second * 3; - } - glBindTexture(GL_TEXTURE_2D,0); - glDisable(GL_TEXTURE_2D); - } - - } - else - { - if(req[INT_ATT_NAMES::ATT_VERTTEXTURE]) - { - if (textureindex.size() > 0) - { - glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D,textureindex[0]); - } - } - else - glDisable(GL_TEXTURE_2D); - - if (_bo[INT_ATT_NAMES::ATT_VERTINDICES]->_isvalid) - { - //qDebug("Indexed drawing"); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,_bo[INT_ATT_NAMES::ATT_VERTINDICES]->_bohandle); - glDrawElements( GL_TRIANGLES, _mesh.FN() * _bo[INT_ATT_NAMES::ATT_VERTINDICES]->_components,GL_UNSIGNED_INT ,NULL); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - - } - - glBindTexture(GL_TEXTURE_2D,0); - glDisable(GL_TEXTURE_2D); - } - InternalRendAtts tmp; - updateClientState(tmp); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0); - glBindBuffer(GL_ARRAY_BUFFER,0); - } - - void drawTrianglesIM(const InternalRendAtts& req,const std::vector& textureindex = std::vector()) const - { - if(_mesh.fn==0) - return; - - bool vn = req[INT_ATT_NAMES::ATT_VERTNORMAL] && vcg::tri::HasPerVertexNormal(_mesh); - bool fn = req[INT_ATT_NAMES::ATT_FACENORMAL] && vcg::tri::HasPerFaceNormal(_mesh); - bool vc = req[INT_ATT_NAMES::ATT_VERTCOLOR] && vcg::tri::HasPerVertexColor(_mesh); - bool fc = req[INT_ATT_NAMES::ATT_FACECOLOR] && vcg::tri::HasPerFaceColor(_mesh); - bool vt = req[INT_ATT_NAMES::ATT_VERTTEXTURE] && vcg::tri::HasPerVertexTexCoord(_mesh); - bool wt = req[INT_ATT_NAMES::ATT_WEDGETEXTURE] && vcg::tri::HasPerWedgeTexCoord(_mesh); + void drawWiredTriangles(const InternalRendAtts& req, const GL_OPTIONS_DERIVED_TYPE* glopts, const std::vector& textureindex = std::vector()) const + { + if (_mesh.VN() == 0) + return; + glPushAttrib(GL_ALL_ATTRIB_BITS); - //typename MESHTYPE::FaceContainer::iterator fp; - typename MESH_TYPE::FaceIterator fi = _mesh.face.begin(); + bool isgloptsvalid = (glopts != NULL); - short curtexname=-1; - if(wt) - { - curtexname=(*fi).WT(0).n(); - if ((curtexname >= 0) && (curtexname < (int)textureindex.size())) - { - glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D,textureindex[curtexname]); - } - else - { - glDisable(GL_TEXTURE_2D); - } - } + if (isgloptsvalid && glopts->_perwire_noshading) + glDisable(GL_LIGHTING); + else + if ((!isgloptsvalid) || (req[INT_ATT_NAMES::ATT_VERTNORMAL])) + { + glEnable(GL_LIGHTING); + } - if(vt && !textureindex.empty()) // in the case of per vertex tex coord we assume that we have a SINGLE texture. - { - curtexname = 0; - glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D,textureindex[curtexname]); - } + glEnable(GL_COLOR_MATERIAL); + if ((isgloptsvalid) && (glopts->_perwire_fixed_color_enabled)) + glColor(glopts->_perwire_fixed_color); + else + { + if ((isgloptsvalid) && (glopts->_perwire_mesh_color_enabled)) + glColor(_mesh.C()); + else + { + if (req[INT_ATT_NAMES::ATT_VERTCOLOR]) + glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); + else + glColor(vcg::Color4b(vcg::Color4b::DarkGray)); + } + } + float linewidth = 1.0f; + if (isgloptsvalid) + linewidth = glopts->_perwire_wirewidth; + glLineWidth(linewidth); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - glBegin(GL_TRIANGLES); + if (isBORenderingAvailable()) + drawTrianglesBO(req, textureindex); + else + drawTrianglesIM(req, textureindex); - while(fi!=_mesh.face.end()) - { - typename MESH_TYPE::FaceType & f = *fi; - if(!f.IsD()) - { - if(wt) - if(f.WT(0).n() != curtexname) - { - curtexname=(*fi).WT(0).n(); - glEnd(); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + glPopAttrib(); + } - if (curtexname >= 0) - { - glEnable(GL_TEXTURE_2D); - if(!textureindex.empty()) - glBindTexture(GL_TEXTURE_2D,textureindex[curtexname]); - } - else - { - glDisable(GL_TEXTURE_2D); - } + void drawTrianglesBO(const InternalRendAtts& req, const std::vector& textureindex = std::vector()) const + { + updateClientState(req); - glBegin(GL_TRIANGLES); - } + bool replicated = InternalRendAtts::replicatedPipelineNeeded(_currallocatedboatt); - if(fn) - glNormal(f.cN()); - if(vn) - glNormal(f.V(0)->cN()); + if (replicated) + { + //qDebug("Replicated drawing"); + int firsttriangleoffset = 0; + if (!req[INT_ATT_NAMES::ATT_VERTTEXTURE] && !req[INT_ATT_NAMES::ATT_WEDGETEXTURE]) + { + glDisable(GL_TEXTURE_2D); + glDrawArrays(GL_TRIANGLES, 0, _mesh.fn * 3); + } + else + { + glEnable(GL_TEXTURE_2D); + for (std::vector< std::pair >::const_iterator it = _texindnumtriangles.begin(); it != _texindnumtriangles.end(); ++it) + { + if ((it->first != -1) && (it->first < textureindex.size())) + glBindTexture(GL_TEXTURE_2D, textureindex[it->first]); + else + glBindTexture(GL_TEXTURE_2D, 0); + glDrawArrays(GL_TRIANGLES, firsttriangleoffset, it->second * 3 - firsttriangleoffset); + firsttriangleoffset = it->second * 3; + } + glBindTexture(GL_TEXTURE_2D, 0); + glDisable(GL_TEXTURE_2D); + } - if(fc) - glColor(f.C()); - if(vc) - glColor(f.V(0)->C()); - if(vt) - glTexCoord(f.V(0)->T().P()); - if(wt) - glTexCoord(f.WT(0).t(0)); - glVertex(f.V(0)->P()); + } + else + { + if (req[INT_ATT_NAMES::ATT_VERTTEXTURE]) + { + if (textureindex.size() > 0) + { + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, textureindex[0]); + } + } + else + glDisable(GL_TEXTURE_2D); - if(vn) - glNormal(f.V(1)->cN()); - if(vc) - glColor(f.V(1)->C()); - if(vt) - glTexCoord(f.V(1)->T().P()); - if(wt) - glTexCoord(f.WT(1).t(0)); - glVertex(f.V(1)->P()); + if (_bo[INT_ATT_NAMES::ATT_VERTINDICES]->_isvalid) + { + //qDebug("Indexed drawing"); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _bo[INT_ATT_NAMES::ATT_VERTINDICES]->_bohandle); + glDrawElements(GL_TRIANGLES, _mesh.FN() * _bo[INT_ATT_NAMES::ATT_VERTINDICES]->_components, GL_UNSIGNED_INT, NULL); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - if(vn) - glNormal(f.V(2)->cN()); - if(vc) - glColor(f.V(2)->C()); - if(vt) - glTexCoord(f.V(2)->T().P()); - if(wt) - glTexCoord(f.WT(2).t(0)); - glVertex(f.V(2)->P()); - } - ++fi; - } + } - glEnd(); - } + glBindTexture(GL_TEXTURE_2D, 0); + glDisable(GL_TEXTURE_2D); + } + InternalRendAtts tmp; + updateClientState(tmp); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } - void drawPoints(const InternalRendAtts& req,GL_OPTIONS_DERIVED_TYPE* glopts, const std::vector& textureindex = std::vector()) const - { - if (_mesh.VN() == 0) - return; - glPushAttrib(GL_ALL_ATTRIB_BITS); - + void drawTrianglesIM(const InternalRendAtts& req, const std::vector& textureindex = std::vector()) const + { + if (_mesh.fn == 0) + return; - bool isgloptsvalid = (glopts != NULL); + bool vn = req[INT_ATT_NAMES::ATT_VERTNORMAL] && vcg::tri::HasPerVertexNormal(_mesh); + bool fn = req[INT_ATT_NAMES::ATT_FACENORMAL] && vcg::tri::HasPerFaceNormal(_mesh); + bool vc = req[INT_ATT_NAMES::ATT_VERTCOLOR] && vcg::tri::HasPerVertexColor(_mesh); + bool fc = req[INT_ATT_NAMES::ATT_FACECOLOR] && vcg::tri::HasPerFaceColor(_mesh); + bool vt = req[INT_ATT_NAMES::ATT_VERTTEXTURE] && vcg::tri::HasPerVertexTexCoord(_mesh); + bool wt = req[INT_ATT_NAMES::ATT_WEDGETEXTURE] && vcg::tri::HasPerWedgeTexCoord(_mesh); - - if ((isgloptsvalid && glopts->_perpoint_noshading) || (isgloptsvalid && glopts->_perpoint_dot_enabled)) - glDisable(GL_LIGHTING); - else - if ((!isgloptsvalid) || req[INT_ATT_NAMES::ATT_VERTNORMAL]) - { - glEnable(GL_LIGHTING); - } - glEnable(GL_COLOR_MATERIAL); - if ((isgloptsvalid) && ((glopts->_perpoint_fixed_color_enabled) || (glopts->_perpoint_mesh_color_enabled))){ - if (glopts->_perpoint_fixed_color_enabled) - glColor(glopts->_perpoint_fixed_color); - else - glColor(_mesh.C()); - } + //typename MESHTYPE::FaceContainer::iterator fp; + typename MESH_TYPE::FaceIterator fi = _mesh.face.begin(); + + short curtexname = -1; + if (wt) + { + curtexname = (*fi).WT(0).n(); + if ((curtexname >= 0) && (curtexname < (int)textureindex.size())) + { + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, textureindex[curtexname]); + } + else + { + glDisable(GL_TEXTURE_2D); + } + } + + if (vt && !textureindex.empty()) // in the case of per vertex tex coord we assume that we have a SINGLE texture. + { + curtexname = 0; + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, textureindex[curtexname]); + } + + glBegin(GL_TRIANGLES); + + while (fi != _mesh.face.end()) + { + typename MESH_TYPE::FaceType & f = *fi; + if (!f.IsD()) + { + if (wt) + if (f.WT(0).n() != curtexname) + { + curtexname = (*fi).WT(0).n(); + glEnd(); + + if (curtexname >= 0) + { + glEnable(GL_TEXTURE_2D); + if (!textureindex.empty()) + glBindTexture(GL_TEXTURE_2D, textureindex[curtexname]); + } + else + { + glDisable(GL_TEXTURE_2D); + } + + glBegin(GL_TRIANGLES); + } + + if (fn) + glNormal(f.cN()); + if (vn) + glNormal(f.V(0)->cN()); + + if (fc) + glColor(f.C()); + if (vc) + glColor(f.V(0)->C()); + if (vt) + glTexCoord(f.V(0)->T().P()); + if (wt) + glTexCoord(f.WT(0).t(0)); + glVertex(f.V(0)->P()); + + if (vn) + glNormal(f.V(1)->cN()); + if (vc) + glColor(f.V(1)->C()); + if (vt) + glTexCoord(f.V(1)->T().P()); + if (wt) + glTexCoord(f.WT(1).t(0)); + glVertex(f.V(1)->P()); + + if (vn) + glNormal(f.V(2)->cN()); + if (vc) + glColor(f.V(2)->C()); + if (vt) + glTexCoord(f.V(2)->T().P()); + if (wt) + glTexCoord(f.WT(2).t(0)); + glVertex(f.V(2)->P()); + } + ++fi; + } + + glEnd(); + } + + void drawPoints(const InternalRendAtts& req, GL_OPTIONS_DERIVED_TYPE* glopts, const std::vector& textureindex = std::vector()) const + { + if (_mesh.VN() == 0) + return; + glPushAttrib(GL_ALL_ATTRIB_BITS); + + + bool isgloptsvalid = (glopts != NULL); + + + if ((isgloptsvalid && glopts->_perpoint_noshading) || (isgloptsvalid && glopts->_perpoint_dot_enabled)) + glDisable(GL_LIGHTING); + else + if ((!isgloptsvalid) || req[INT_ATT_NAMES::ATT_VERTNORMAL]) + { + glEnable(GL_LIGHTING); + } + + glEnable(GL_COLOR_MATERIAL); + if ((isgloptsvalid) && ((glopts->_perpoint_fixed_color_enabled) || (glopts->_perpoint_mesh_color_enabled))) { + if (glopts->_perpoint_fixed_color_enabled) + glColor(glopts->_perpoint_fixed_color); + else + glColor(_mesh.C()); + } + + if (req[INT_ATT_NAMES::ATT_VERTCOLOR]) + glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); - if (req[INT_ATT_NAMES::ATT_VERTCOLOR]) - glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE); - if (req[INT_ATT_NAMES::ATT_VERTTEXTURE]) { @@ -1668,36 +1669,36 @@ namespace vcg } else glDisable(GL_TEXTURE_2D); - //glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _bo[GLMeshAttributesInfo::ATT_VERTINDEX]->_bohandle); - - if (glopts != NULL) - { + //glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _bo[GLMeshAttributesInfo::ATT_VERTINDEX]->_bohandle); + + if (glopts != NULL) + { if (!glopts->_perpoint_dot_enabled) glPointSize(glopts->_perpoint_pointsize); - if ((glopts->_perpoint_pointsmooth_enabled) || (glopts->_perpoint_dot_enabled)) - glEnable(GL_POINT_SMOOTH); - else - glDisable(GL_POINT_SMOOTH); - if(glopts->_perpoint_pointattenuation_enabled) - { - vcg::Matrix44 mat; - glGetv(GL_MODELVIEW_MATRIX,mat); - vcg::Point3 c =_mesh.bbox.Center(); - float camDist = (float)Norm(mat*c); - float quadratic[] = { 0.0f, 0.0f, 1.0f/(camDist*camDist) , 0.0f }; - glPointParameterfv( GL_POINT_DISTANCE_ATTENUATION, quadratic ); - glPointParameterf( GL_POINT_SIZE_MAX, 16.0f ); - glPointParameterf( GL_POINT_SIZE_MIN, 1.0f ); - } - else - { - float quadratic[] = { 1.0f, 0.0f, 0.0f}; - glPointParameterfv( GL_POINT_DISTANCE_ATTENUATION, quadratic ); - float pointsize = 1.0f; - if (isgloptsvalid) - pointsize = glopts->_perpoint_pointsize; - glPointSize(pointsize); - } + if ((glopts->_perpoint_pointsmooth_enabled) || (glopts->_perpoint_dot_enabled)) + glEnable(GL_POINT_SMOOTH); + else + glDisable(GL_POINT_SMOOTH); + if (glopts->_perpoint_pointattenuation_enabled) + { + vcg::Matrix44 mat; + glGetv(GL_MODELVIEW_MATRIX, mat); + vcg::Point3 c = _mesh.bbox.Center(); + float camDist = (float)Norm(mat*c); + float quadratic[] = { 0.0f, 0.0f, 1.0f / (camDist*camDist) , 0.0f }; + glPointParameterfv(GL_POINT_DISTANCE_ATTENUATION, quadratic); + glPointParameterf(GL_POINT_SIZE_MAX, 16.0f); + glPointParameterf(GL_POINT_SIZE_MIN, 1.0f); + } + else + { + float quadratic[] = { 1.0f, 0.0f, 0.0f }; + glPointParameterfv(GL_POINT_DISTANCE_ATTENUATION, quadratic); + float pointsize = 1.0f; + if (isgloptsvalid) + pointsize = glopts->_perpoint_pointsize; + glPointSize(pointsize); + } if (glopts->_perpoint_dot_enabled) { glEnable(GL_BLEND); @@ -1706,11 +1707,11 @@ namespace vcg glDepthFunc(GL_LEQUAL); glPointSize(glopts->_perpoint_pointsize + 0.5); } - } - if (isBORenderingAvailable()) - drawPointsBO(req); - else - drawPointsIM(req); + } + if (isBORenderingAvailable()) + drawPointsBO(req); + else + drawPointsIM(req); if ((glopts != NULL) && (glopts->_perpoint_dot_enabled)) { @@ -1723,66 +1724,66 @@ namespace vcg else drawPointsIM(req); } - glPopAttrib(); - } + glPopAttrib(); + } - void drawPointsBO(const InternalRendAtts& req) const - { - size_t pointsnum = _mesh.VN(); - if (InternalRendAtts::replicatedPipelineNeeded(_currallocatedboatt)) - pointsnum = _mesh.FN() * 3; - updateClientState(req); - glDrawArrays(GL_POINTS,0,GLsizei(pointsnum)); - /*disable all client state buffers*/ - InternalRendAtts tmp; - updateClientState(tmp); - } + void drawPointsBO(const InternalRendAtts& req) const + { + size_t pointsnum = _mesh.VN(); + if (InternalRendAtts::replicatedPipelineNeeded(_currallocatedboatt)) + pointsnum = _mesh.FN() * 3; + updateClientState(req); + glDrawArrays(GL_POINTS, 0, GLsizei(pointsnum)); + /*disable all client state buffers*/ + InternalRendAtts tmp; + updateClientState(tmp); + } - void drawPointsIM(const InternalRendAtts& req) const - { - bool vn = req[INT_ATT_NAMES::ATT_VERTNORMAL] && vcg::tri::HasPerVertexNormal(_mesh); - bool vc = req[INT_ATT_NAMES::ATT_VERTCOLOR] && vcg::tri::HasPerVertexColor(_mesh); - bool vt = req[INT_ATT_NAMES::ATT_VERTTEXTURE] && vcg::tri::HasPerVertexTexCoord(_mesh); - + void drawPointsIM(const InternalRendAtts& req) const + { + bool vn = req[INT_ATT_NAMES::ATT_VERTNORMAL] && vcg::tri::HasPerVertexNormal(_mesh); + bool vc = req[INT_ATT_NAMES::ATT_VERTCOLOR] && vcg::tri::HasPerVertexColor(_mesh); + bool vt = req[INT_ATT_NAMES::ATT_VERTTEXTURE] && vcg::tri::HasPerVertexTexCoord(_mesh); - glBegin(GL_POINTS); - for(typename MESH_TYPE::VertexIterator vi=_mesh.vert.begin();vi!=_mesh.vert.end();++vi) - { - if(!(*vi).IsD()) - { - if(vn) glNormal((*vi).cN()); - if(vc) glColor((*vi).C()); - if(vt) glTexCoord((*vi).T().P()); - glVertex((*vi).P()); - } - } - glEnd(); - } - void drawEdges(const InternalRendAtts& req,GL_OPTIONS_DERIVED_TYPE* glopts) const - { - if (_mesh.VN() == 0) - return; - glPushAttrib(GL_ALL_ATTRIB_BITS); - - bool isgloptsvalid = (glopts != NULL); + glBegin(GL_POINTS); + for (typename MESH_TYPE::VertexIterator vi = _mesh.vert.begin(); vi != _mesh.vert.end(); ++vi) + { + if (!(*vi).IsD()) + { + if (vn) glNormal((*vi).cN()); + if (vc) glColor((*vi).C()); + if (vt) glTexCoord((*vi).T().P()); + glVertex((*vi).P()); + } + } + glEnd(); + } - glEnable(GL_COLOR_MATERIAL); - glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE); + void drawEdges(const InternalRendAtts& req, GL_OPTIONS_DERIVED_TYPE* glopts) const + { + if (_mesh.VN() == 0) + return; + glPushAttrib(GL_ALL_ATTRIB_BITS); - if (isgloptsvalid && glopts->_perwire_noshading) - glDisable(GL_LIGHTING); - else - if ((!isgloptsvalid) || (req[INT_ATT_NAMES::ATT_VERTNORMAL])) - { - glEnable(GL_LIGHTING); - } + bool isgloptsvalid = (glopts != NULL); - bool colordefinedenabled = (isgloptsvalid) && ((glopts->_perwire_fixed_color_enabled) || (glopts->_perwire_mesh_color_enabled)); + glEnable(GL_COLOR_MATERIAL); + glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); - if (!(isgloptsvalid) || colordefinedenabled) - { - vcg::Color4b tmpcol = vcg::Color4b(vcg::Color4b::DarkGray); + if (isgloptsvalid && glopts->_perwire_noshading) + glDisable(GL_LIGHTING); + else + if ((!isgloptsvalid) || (req[INT_ATT_NAMES::ATT_VERTNORMAL])) + { + glEnable(GL_LIGHTING); + } + + bool colordefinedenabled = (isgloptsvalid) && ((glopts->_perwire_fixed_color_enabled) || (glopts->_perwire_mesh_color_enabled)); + + if (!(isgloptsvalid) || colordefinedenabled) + { + vcg::Color4b tmpcol = vcg::Color4b(vcg::Color4b::DarkGray); if (colordefinedenabled) { if (glopts->_perwire_fixed_color_enabled) @@ -1790,590 +1791,590 @@ namespace vcg else tmpcol = _mesh.cC(); } - glColor(tmpcol); - } - - glDisable(GL_TEXTURE_2D); - //glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _bo[GLMeshAttributesInfo::ATT_VERTINDEX]->_bohandle); - - float linewidth = 1.0f; - if (isgloptsvalid) - linewidth = glopts->_perwire_wirewidth; - glLineWidth(linewidth); - - if (isBORenderingAvailable()) - drawEdgesBO(req); - else - drawEdgesIM(req); - //glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - - /*disable all client state buffers*/ - glPopAttrib(); - } - - void drawEdgesBO(const InternalRendAtts& req) const - { - if (_bo[INT_ATT_NAMES::ATT_EDGEINDICES]->_isvalid) - { - //qDebug("Indexed drawing"); - updateClientState(req); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,_bo[INT_ATT_NAMES::ATT_EDGEINDICES]->_bohandle); - glDrawElements( GL_LINES, _edge.size() * _bo[INT_ATT_NAMES::ATT_EDGEINDICES]->_components,GL_UNSIGNED_INT ,NULL); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - InternalRendAtts tmp; - updateClientState(tmp); - } - } - - void drawEdgesIM(const InternalRendAtts& req) const - { - typename MESH_TYPE::FaceIterator fi = _mesh.face.begin(); - - bool vn = req[INT_ATT_NAMES::ATT_VERTNORMAL] && vcg::tri::HasPerVertexNormal(_mesh); - bool vc = req[INT_ATT_NAMES::ATT_VERTCOLOR] && vcg::tri::HasPerVertexColor(_mesh); - - glBegin(GL_LINES); - - while(fi!=_mesh.face.end()) - { - typename MESH_TYPE::FaceType & f = *fi; - - if(!f.IsD()) - { - if (!f.IsF(0)) - { - if(vn) glNormal(f.V(0)->cN()); - if(vc) glColor(f.V(0)->C()); - glVertex(f.V(0)->P()); - - if(vn) glNormal(f.V(1)->cN()); - - if(vc) glColor(f.V(1)->C()); - glVertex(f.V(1)->P()); - } - - if (!f.IsF(1)) - { - if(vn) glNormal(f.V(1)->cN()); - if(vc) glColor(f.V(1)->C()); - glVertex(f.V(1)->P()); - - if(vn) glNormal(f.V(2)->cN()); - if(vc) glColor(f.V(2)->C()); - glVertex(f.V(2)->P()); - } - - if (!f.IsF(2)) - { - if(vn) glNormal(f.V(2)->cN()); - if(vc) glColor(f.V(2)->C()); - glVertex(f.V(2)->P()); - - if(vn) glNormal(f.V(0)->cN()); - if(vc) glColor(f.V(0)->C()); - glVertex(f.V(0)->P()); - } - - } - ++fi; - } - - glEnd(); - } - - void drawBBox(GL_OPTIONS_DERIVED_TYPE* glopts) const - { - glPushAttrib(GL_ALL_ATTRIB_BITS); - bool isgloptsvalid = (glopts != NULL); - - glDisable(GL_LIGHTING); - glEnable(GL_COLOR_MATERIAL); - glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE); - - if ((isgloptsvalid) && (glopts->_perbbox_fixed_color_enabled)) - glColor(glopts->_perbbox_fixed_color); - else - { - if ((isgloptsvalid) && (glopts->_perbbox_mesh_color_enabled)) - glColor(_mesh.C()); - else - glColor(vcg::Color4b(vcg::Color4b::White)); - } - if (isBORenderingAvailable()) - drawBBoxBO(); - else - drawBBoxIM(); - glPopAttrib(); - } - - void drawBBoxBO() const - { - vcg::Box3& b = _mesh.bbox; - - GLuint bbhandle; - glGenBuffers(1,&bbhandle); - std::vector bbox(12 * 2); - - //0 - bbox[0] = vcg::Point3f((float)b.min[0],(float)b.min[1],(float)b.min[2]); - bbox[1] = vcg::Point3f((float)b.max[0],(float)b.min[1],(float)b.min[2]); - - //1 - bbox[2] = vcg::Point3f((float)b.max[0],(float)b.min[1],(float)b.min[2]); - bbox[3] = vcg::Point3f((float)b.max[0],(float)b.max[1],(float)b.min[2]); - - //2 - bbox[4] = vcg::Point3f((float)b.max[0],(float)b.max[1],(float)b.min[2]); - bbox[5] = vcg::Point3f((float)b.min[0],(float)b.max[1],(float)b.min[2]); - - //3 - bbox[6] = vcg::Point3f((float)b.min[0],(float)b.max[1],(float)b.min[2]); - bbox[7] = vcg::Point3f((float)b.min[0],(float)b.min[1],(float)b.min[2]); - - //4 - bbox[8] = vcg::Point3f((float)b.min[0],(float)b.min[1],(float)b.min[2]); - bbox[9] = vcg::Point3f((float)b.min[0],(float)b.min[1],(float)b.max[2]); - - //5 - bbox[10] = vcg::Point3f((float)b.min[0],(float)b.min[1],(float)b.max[2]); - bbox[11] = vcg::Point3f((float)b.max[0],(float)b.min[1],(float)b.max[2]); - - //6 - bbox[12] = vcg::Point3f((float)b.max[0],(float)b.min[1],(float)b.max[2]); - bbox[13] = vcg::Point3f((float)b.max[0],(float)b.min[1],(float)b.min[2]); - - //7 - bbox[14] = vcg::Point3f((float)b.max[0],(float)b.min[1],(float)b.max[2]); - bbox[15] = vcg::Point3f((float)b.max[0],(float)b.max[1],(float)b.max[2]); - - //8 - bbox[16] = vcg::Point3f((float)b.max[0],(float)b.max[1],(float)b.max[2]); - bbox[17] = vcg::Point3f((float)b.max[0],(float)b.max[1],(float)b.min[2]); - - //9 - bbox[18] = vcg::Point3f((float)b.max[0],(float)b.max[1],(float)b.max[2]); - bbox[19] = vcg::Point3f((float)b.min[0],(float)b.max[1],(float)b.max[2]); - - //10 - bbox[20] = vcg::Point3f((float)b.min[0],(float)b.max[1],(float)b.max[2]); - bbox[21] = vcg::Point3f((float)b.min[0],(float)b.min[1],(float)b.max[2]); - - //11 - bbox[22] = vcg::Point3f((float)b.min[0],(float)b.max[1],(float)b.max[2]); - bbox[23] = vcg::Point3f((float)b.min[0],(float)b.max[1],(float)b.min[2]); - - glBindBuffer(GL_ARRAY_BUFFER,bbhandle); - glBufferData(GL_ARRAY_BUFFER, 12 * 2 * sizeof(vcg::Point3f), &(bbox[0]), GL_STATIC_DRAW); - glVertexPointer(3,GL_FLOAT,0,0); - glBindBuffer(GL_ARRAY_BUFFER,0); - glEnableClientState(GL_VERTEX_ARRAY); - glDrawArrays(GL_LINES,0,24); - glDisableClientState(GL_VERTEX_ARRAY); - glDeleteBuffers(1,&bbhandle); - } - - void drawBBoxIM() const - { - vcg::Box3& b = _mesh.bbox; - - glBegin(GL_LINE_STRIP); - glVertex3f((float)b.min[0],(float)b.min[1],(float)b.min[2]); - glVertex3f((float)b.max[0],(float)b.min[1],(float)b.min[2]); - glVertex3f((float)b.max[0],(float)b.max[1],(float)b.min[2]); - glVertex3f((float)b.min[0],(float)b.max[1],(float)b.min[2]); - glVertex3f((float)b.min[0],(float)b.min[1],(float)b.min[2]); - glEnd(); - glBegin(GL_LINE_STRIP); - glVertex3f((float)b.min[0],(float)b.min[1],(float)b.max[2]); - glVertex3f((float)b.max[0],(float)b.min[1],(float)b.max[2]); - glVertex3f((float)b.max[0],(float)b.max[1],(float)b.max[2]); - glVertex3f((float)b.min[0],(float)b.max[1],(float)b.max[2]); - glVertex3f((float)b.min[0],(float)b.min[1],(float)b.max[2]); - glEnd(); - glBegin(GL_LINES); - glVertex3f((float)b.min[0],(float)b.min[1],(float)b.min[2]); - glVertex3f((float)b.min[0],(float)b.min[1],(float)b.max[2]); - - glVertex3f((float)b.max[0],(float)b.min[1],(float)b.min[2]); - glVertex3f((float)b.max[0],(float)b.min[1],(float)b.max[2]); - - glVertex3f((float)b.max[0],(float)b.max[1],(float)b.min[2]); - glVertex3f((float)b.max[0],(float)b.max[1],(float)b.max[2]); - - glVertex3f((float)b.min[0],(float)b.max[1],(float)b.min[2]); - glVertex3f((float)b.min[0],(float)b.max[1],(float)b.max[2]); - glEnd(); - } - - void updateClientState(const InternalRendAtts& req) const - { - int ii = 0; - for(typename std::vector::const_iterator it = _bo.begin();it != _bo.end();++it) - { - INT_ATT_NAMES boname(ii); - if ((boname != INT_ATT_NAMES::ATT_VERTINDICES) && (boname != INT_ATT_NAMES::ATT_EDGEINDICES) /*&& (boname != INT_ATT_NAMES::ATT_FIXEDCOLOR)*/) - { - if (req[boname] && _currallocatedboatt[boname] && (*it != NULL)) - { - glBindBuffer((*it)->_target, (*it)->_bohandle); - setBufferPointer(boname); - glEnableClientState((*it)->_clientstatetag); - glBindBuffer((*it)->_target, 0); - } - else - { - glBindBuffer((*it)->_target, (*it)->_bohandle); - disableClientState(boname,req); - glBindBuffer((*it)->_target, 0); - } - } - ++ii; - } - } - - void setBufferPointer( INT_ATT_NAMES boname) const - { - unsigned int ii = boname; - if (ii >= INT_ATT_NAMES::enumArity()) - return; - GLBufferObject* cbo = _bo[ii]; - if (cbo == NULL) - return; - - switch(ii) - { - case(INT_ATT_NAMES::ATT_VERTPOSITION): - { - glVertexPointer(GLint(cbo->_components), cbo->_gltype, GLsizei(0), 0); - break; - } - case(INT_ATT_NAMES::ATT_VERTNORMAL): - case(INT_ATT_NAMES::ATT_FACENORMAL): - { - glNormalPointer(cbo->_gltype, GLsizei(0), 0); - break; - } - case(INT_ATT_NAMES::ATT_VERTCOLOR): - case(INT_ATT_NAMES::ATT_FACECOLOR): - { - glColorPointer(GLint(cbo->_components), cbo->_gltype, GLsizei(0), 0); - break; - } - case(INT_ATT_NAMES::ATT_VERTTEXTURE): - case(INT_ATT_NAMES::ATT_WEDGETEXTURE): - { - glTexCoordPointer(GLint(cbo->_components), cbo->_gltype,GLsizei(0), 0); - break; - } - default : break; - } - } - - void disableClientState( INT_ATT_NAMES boname,const RendAtts& req) const - { - - if (boname >= INT_ATT_NAMES::enumArity()) - return; - - switch(boname) - { - case(INT_ATT_NAMES::ATT_VERTPOSITION): - { - glDisableClientState(GL_VERTEX_ARRAY); - break; - } - case(INT_ATT_NAMES::ATT_VERTNORMAL): - case(INT_ATT_NAMES::ATT_FACENORMAL): - { - if (!req[INT_ATT_NAMES::ATT_VERTNORMAL] && !req[INT_ATT_NAMES::ATT_FACENORMAL]) - glDisableClientState(GL_NORMAL_ARRAY); - break; - } - case(INT_ATT_NAMES::ATT_VERTCOLOR): - case(INT_ATT_NAMES::ATT_FACECOLOR): - { - if (!req[INT_ATT_NAMES::ATT_VERTCOLOR] && !req[INT_ATT_NAMES::ATT_FACECOLOR]) - glDisableClientState(GL_COLOR_ARRAY); - break; - } - case(INT_ATT_NAMES::ATT_VERTTEXTURE): - case(INT_ATT_NAMES::ATT_WEDGETEXTURE): - { - if (!req[INT_ATT_NAMES::ATT_VERTTEXTURE] && !req[INT_ATT_NAMES::ATT_WEDGETEXTURE]) - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - break; - } - default: - { - break; - } - - } - } - - void fillchunkMap() - { - if (!vcg::tri::HasPerWedgeTexCoord(_mesh)) - return; - _chunkmap.clear(); - typename MESH_TYPE::FaceIterator infrange = _mesh.face.begin(); - short texind = std::numeric_limits::max(); - int hh = 0; - for(typename MESH_TYPE::FaceIterator fit = _mesh.face.begin();fit != _mesh.face.end();++fit) - { - if (fit->WT(0).N() != texind) - { - if ((texind != std::numeric_limits::max()) || (fit == _mesh.face.end() - 1)) - { - GLuint lowind = std::distance(_mesh.face.begin(),infrange); - GLuint topind = std::distance(_mesh.face.begin(),fit) - 1; - _chunkmap[texind].push_back(std::make_pair(lowind,topind)); - infrange = fit; - } - texind = fit->WT(0).N(); - } - ++hh; - } - _chunkmap[texind].push_back(std::make_pair(std::distance(_mesh.face.begin(),infrange),std::distance(_mesh.face.begin(),_mesh.face.end() - 1))); - } - - void debug(const InternalRendAtts& tobeallocated,const InternalRendAtts& tobedeallocated,const InternalRendAtts& tobeupdated) - { - _loginfo.reset(); - _loginfo._tobedeallocated = std::string("to_be_deallocated: "); - _loginfo._tobeallocated = std::string("to_be_allocated: "); - _loginfo._tobeupdated = std::string("to_be_updated: "); - - std::string truestring("true"); - std::string falsestring("false"); - for(unsigned int ii = 0;ii < INT_ATT_NAMES::enumArity();++ii) - { - std::string deallocres(falsestring); - if (tobedeallocated[ii]) - deallocres = truestring; - _loginfo._tobedeallocated += deallocres + " "; - - std::string allocres(falsestring); - if (tobeallocated[ii]) - allocres = truestring; - _loginfo._tobeallocated += allocres + " "; - - std::string upres(falsestring); - if (tobeupdated[ii]) - upres = truestring; - _loginfo._tobeupdated += upres + " "; - } - - _loginfo._tobedeallocated = std::string("[") + _loginfo._tobedeallocated + std::string("]"); - _loginfo._tobeallocated = std::string("[") + _loginfo._tobeallocated + std::string("]"); - _loginfo._tobeupdated = std::string("[") + _loginfo._tobeupdated + std::string("]"); - - - int hh = 0; - - for(typename ViewsMap::const_iterator it = _perviewreqatts.begin();it != _perviewreqatts.end();++it) - { - std::stringstream tmpstream; - tmpstream << "view_" << hh << ":\n"; - for(size_t pm = 0; pm < size_t(PR_ARITY); ++pm) - { - tmpstream << DebugInfo::primitiveName(pm) << " "; - - for(unsigned int ii = 0;ii < INT_ATT_NAMES::enumArity();++ii) - { - std::string res = falsestring; - if (it->second._intatts[pm][ii]) - res = truestring; - tmpstream << "att[" << ii << "]=" << res << " "; - } - tmpstream << std::endl; - } - _loginfo._perviewdata.push_back(tmpstream.str()); - ++hh; - } - - std::stringstream tmpstream; - tmpstream << "currently_allocated: " ; - for(unsigned int ii = 0;ii < INT_ATT_NAMES::enumArity();++ii) - { - std::string res = falsestring; - if (_currallocatedboatt[ii]) - res = truestring; - tmpstream << "att[" << ii << "]=" << res << " "; - } - _loginfo._currentlyallocated = tmpstream.str(); - } - - class EdgeVertInd - { - public: - - GLuint _v[2]; // the two Vertex indices are ordered! - - EdgeVertInd() {} - EdgeVertInd(const MESH_TYPE& m,typename MESH_TYPE::FacePointer pf, const int nz) { this->set(m,pf,nz); } - EdgeVertInd(const MESH_TYPE& m,typename MESH_TYPE::EdgePointer pe, const int nz) { this->set(m,pe,nz); } - - void set(const MESH_TYPE& m,typename MESH_TYPE::FacePointer pf, const int nz ) - { - assert(pf!=0); - assert(nz>=0); - assert(nzVN()); - - _v[0] = GLuint(vcg::tri::Index(m,pf->V(nz)));; - _v[1] = GLuint(vcg::tri::Index(m,pf->V(pf->Next(nz)))); - assert(_v[0] != _v[1]); // The face pointed by 'f' is Degenerate (two coincident vertexes) - - if( _v[0] > _v[1] ) - std::swap(_v[0],_v[1]); - } - - void set(const MESH_TYPE& m,typename MESH_TYPE::EdgePointer pe,const int nz) - { - assert(pe!=0); - assert(nz>=0); - assert(nz<2); - - _v[0] = size_t(vcg::tri::Index(m,pe->V(nz)));; - _v[1] = size_t(vcg::tri::Index(m,pe->V((nz + 1)%2))); - assert(_v[0] != _v[1]); // The face pointed by 'f' is Degenerate (two coincident vertexes) - - if( _v[0] > _v[1] ) - std::swap(_v[0],_v[1]); - } - - inline bool operator<(const EdgeVertInd& pe) const - { - if(_v[0]pe._v[0] ) - return false; - else - return _v[1] < pe._v[1]; - } - - inline bool operator==( const EdgeVertInd & pe ) const - { - return _v[0]==pe._v[0] && _v[1]==pe._v[1]; - } - }; - - static void fillEdgeVector(MESH_TYPE &m, std::vector &edgeVec, bool includeFauxEdge=true) - { - if (m.FN() > 0) - { - edgeVec.reserve(m.FN()*3); - for(typename MESH_TYPE::FaceIterator fi=m.face.begin();fi!=m.face.end();++fi) - if( ! (*fi).IsD() ) - for(int j=0;j<(*fi).VN();++j) - if(includeFauxEdge || !(*fi).IsF(j)) - edgeVec.push_back(EdgeVertInd(m,&*fi,j)); - } - else - if ((m.VN() > 0) && (m.EN() > 0) ) - { - edgeVec.reserve(m.EN()*2); - for(typename MESH_TYPE::EdgeIterator ei=m.edge.begin();ei!=m.edge.end();++ei) - if( ! (*ei).IsD() ) - for(int j=0;j<2;++j) - edgeVec.push_back(EdgeVertInd(m,&*ei,j)); - } - - } - - static void fillUniqueEdgeVector(MESH_TYPE &m, std::vector &edgeVec) - { - fillEdgeVector(m,edgeVec,false); - std::sort(edgeVec.begin(), edgeVec.end()); - - typename std::vector::iterator newEnd = std::unique(edgeVec.begin(), edgeVec.end()); - - edgeVec.resize(newEnd-edgeVec.begin()); - } - - struct GLBufferObject - { - GLBufferObject(size_t components,GLenum gltype,GLenum clientstatetag,GLenum target) - :_size(0),_components(components),_isvalid(false),_gltype(gltype),_clientstatetag(clientstatetag),_target(target),_bohandle(0) - { - } - - GLBufferObject(size_t components,GLenum gltype,GLenum target) - :_size(0),_components(components),_isvalid(false),_gltype(gltype),_clientstatetag(),_target(target),_bohandle(0) - { - } - - size_t getSizeOfGLType() const - { - switch(_gltype) - { - case(GL_FLOAT): - return sizeof(GLfloat); - case(GL_INT): - return sizeof(GLint); - case(GL_UNSIGNED_INT): - return sizeof(GLuint); - case(GL_UNSIGNED_BYTE): - return sizeof(GLubyte); - } - return 0; - } - - size_t _size; - const size_t _components; - bool _isvalid; - const GLenum _gltype; - const GLenum _target; - - /*WARNING!!!!!!!!!!!!!!!!! In openGL INDEX BO doesn't require to be enabled/disabled so has NOT a valid tag associated. - In this case the client state tag remains not initialized and it's not meaningful */ - const GLenum _clientstatetag; - /**********************************************************************************/ - - GLuint _bohandle; - }; - - //ideally this should be const. I'm not yet sure if VCGLib will allow me to declare it as constant - MESH_TYPE& _mesh; - - MemoryInfo& _gpumeminfo; - - /*The buffer objects used for the rendering operation. They are shared among all the views*/ - std::vector _bo; - - typedef std::map< UNIQUE_VIEW_ID_TYPE,PVData > ViewsMap; - - ///*_perviewreqatts contains a map of the requested atts by each single view. it's maintained for the actual rendering step*/ - ViewsMap _perviewreqatts; - - /*_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*/ - /* WARNING!!!! The currently allocated BOs are the union of all the BOs requested to be visualized in the _perviewreqatts plus, possibly, the edgeindex bo (depending by the kind of per view render primitive modality that is requested) and the vertexindex bo (depending of the solid rendering modality, per-face/per-vertex)*/ - /* The EdgeIndex bo is allocated only if one of the requested rendering modality is PR_WIREFRAME_EDGES or PR_WIREFRAME_EDGES. If we have PR_SOLID the glPolygonMode function is used for rendering the triangle wireframe view*/ - InternalRendAtts _currallocatedboatt; - - bool _borendering; - size_t _perbatchprim; - - /*Additional structures used for per wedge texturing modality*/ - typedef std::vector< std::pair< GLuint,GLuint > > ChunkVector; - typedef std::map< short, ChunkVector > ChunkMap; - - std::vector< std::pair > _texindnumtriangles; - ChunkMap _chunkmap; - - //Horrible waste of memory space...but computing the list of edges is too much expensive...we must minimize it! - std::vector _edge; - size_t _meshverticeswhenedgeindiceswerecomputed; - size_t _meshtriangleswhenedgeindiceswerecomputed; - - //vcg::GLOptions _glopts; - vcg::Matrix44 _tr; - - bool _debugmode; - DebugInfo _loginfo; - - std::vector _meaningfulattsperprimitive; - }; + glColor(tmpcol); + } + + glDisable(GL_TEXTURE_2D); + //glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _bo[GLMeshAttributesInfo::ATT_VERTINDEX]->_bohandle); + + float linewidth = 1.0f; + if (isgloptsvalid) + linewidth = glopts->_perwire_wirewidth; + glLineWidth(linewidth); + + if (isBORenderingAvailable()) + drawEdgesBO(req); + else + drawEdgesIM(req); + //glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + /*disable all client state buffers*/ + glPopAttrib(); + } + + void drawEdgesBO(const InternalRendAtts& req) const + { + if (_bo[INT_ATT_NAMES::ATT_EDGEINDICES]->_isvalid) + { + //qDebug("Indexed drawing"); + updateClientState(req); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _bo[INT_ATT_NAMES::ATT_EDGEINDICES]->_bohandle); + glDrawElements(GL_LINES, _edge.size() * _bo[INT_ATT_NAMES::ATT_EDGEINDICES]->_components, GL_UNSIGNED_INT, NULL); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + InternalRendAtts tmp; + updateClientState(tmp); + } + } + + void drawEdgesIM(const InternalRendAtts& req) const + { + typename MESH_TYPE::FaceIterator fi = _mesh.face.begin(); + + bool vn = req[INT_ATT_NAMES::ATT_VERTNORMAL] && vcg::tri::HasPerVertexNormal(_mesh); + bool vc = req[INT_ATT_NAMES::ATT_VERTCOLOR] && vcg::tri::HasPerVertexColor(_mesh); + + glBegin(GL_LINES); + + while (fi != _mesh.face.end()) + { + typename MESH_TYPE::FaceType & f = *fi; + + if (!f.IsD()) + { + if (!f.IsF(0)) + { + if (vn) glNormal(f.V(0)->cN()); + if (vc) glColor(f.V(0)->C()); + glVertex(f.V(0)->P()); + + if (vn) glNormal(f.V(1)->cN()); + + if (vc) glColor(f.V(1)->C()); + glVertex(f.V(1)->P()); + } + + if (!f.IsF(1)) + { + if (vn) glNormal(f.V(1)->cN()); + if (vc) glColor(f.V(1)->C()); + glVertex(f.V(1)->P()); + + if (vn) glNormal(f.V(2)->cN()); + if (vc) glColor(f.V(2)->C()); + glVertex(f.V(2)->P()); + } + + if (!f.IsF(2)) + { + if (vn) glNormal(f.V(2)->cN()); + if (vc) glColor(f.V(2)->C()); + glVertex(f.V(2)->P()); + + if (vn) glNormal(f.V(0)->cN()); + if (vc) glColor(f.V(0)->C()); + glVertex(f.V(0)->P()); + } + + } + ++fi; + } + + glEnd(); + } + + void drawBBox(GL_OPTIONS_DERIVED_TYPE* glopts) const + { + glPushAttrib(GL_ALL_ATTRIB_BITS); + bool isgloptsvalid = (glopts != NULL); + + glDisable(GL_LIGHTING); + glEnable(GL_COLOR_MATERIAL); + glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); + + if ((isgloptsvalid) && (glopts->_perbbox_fixed_color_enabled)) + glColor(glopts->_perbbox_fixed_color); + else + { + if ((isgloptsvalid) && (glopts->_perbbox_mesh_color_enabled)) + glColor(_mesh.C()); + else + glColor(vcg::Color4b(vcg::Color4b::White)); + } + if (isBORenderingAvailable()) + drawBBoxBO(); + else + drawBBoxIM(); + glPopAttrib(); + } + + void drawBBoxBO() const + { + vcg::Box3& b = _mesh.bbox; + + GLuint bbhandle; + glGenBuffers(1, &bbhandle); + std::vector bbox(12 * 2); + + //0 + bbox[0] = vcg::Point3f((float)b.min[0], (float)b.min[1], (float)b.min[2]); + bbox[1] = vcg::Point3f((float)b.max[0], (float)b.min[1], (float)b.min[2]); + + //1 + bbox[2] = vcg::Point3f((float)b.max[0], (float)b.min[1], (float)b.min[2]); + bbox[3] = vcg::Point3f((float)b.max[0], (float)b.max[1], (float)b.min[2]); + + //2 + bbox[4] = vcg::Point3f((float)b.max[0], (float)b.max[1], (float)b.min[2]); + bbox[5] = vcg::Point3f((float)b.min[0], (float)b.max[1], (float)b.min[2]); + + //3 + bbox[6] = vcg::Point3f((float)b.min[0], (float)b.max[1], (float)b.min[2]); + bbox[7] = vcg::Point3f((float)b.min[0], (float)b.min[1], (float)b.min[2]); + + //4 + bbox[8] = vcg::Point3f((float)b.min[0], (float)b.min[1], (float)b.min[2]); + bbox[9] = vcg::Point3f((float)b.min[0], (float)b.min[1], (float)b.max[2]); + + //5 + bbox[10] = vcg::Point3f((float)b.min[0], (float)b.min[1], (float)b.max[2]); + bbox[11] = vcg::Point3f((float)b.max[0], (float)b.min[1], (float)b.max[2]); + + //6 + bbox[12] = vcg::Point3f((float)b.max[0], (float)b.min[1], (float)b.max[2]); + bbox[13] = vcg::Point3f((float)b.max[0], (float)b.min[1], (float)b.min[2]); + + //7 + bbox[14] = vcg::Point3f((float)b.max[0], (float)b.min[1], (float)b.max[2]); + bbox[15] = vcg::Point3f((float)b.max[0], (float)b.max[1], (float)b.max[2]); + + //8 + bbox[16] = vcg::Point3f((float)b.max[0], (float)b.max[1], (float)b.max[2]); + bbox[17] = vcg::Point3f((float)b.max[0], (float)b.max[1], (float)b.min[2]); + + //9 + bbox[18] = vcg::Point3f((float)b.max[0], (float)b.max[1], (float)b.max[2]); + bbox[19] = vcg::Point3f((float)b.min[0], (float)b.max[1], (float)b.max[2]); + + //10 + bbox[20] = vcg::Point3f((float)b.min[0], (float)b.max[1], (float)b.max[2]); + bbox[21] = vcg::Point3f((float)b.min[0], (float)b.min[1], (float)b.max[2]); + + //11 + bbox[22] = vcg::Point3f((float)b.min[0], (float)b.max[1], (float)b.max[2]); + bbox[23] = vcg::Point3f((float)b.min[0], (float)b.max[1], (float)b.min[2]); + + glBindBuffer(GL_ARRAY_BUFFER, bbhandle); + glBufferData(GL_ARRAY_BUFFER, 12 * 2 * sizeof(vcg::Point3f), &(bbox[0]), GL_STATIC_DRAW); + glVertexPointer(3, GL_FLOAT, 0, 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glEnableClientState(GL_VERTEX_ARRAY); + glDrawArrays(GL_LINES, 0, 24); + glDisableClientState(GL_VERTEX_ARRAY); + glDeleteBuffers(1, &bbhandle); + } + + void drawBBoxIM() const + { + vcg::Box3& b = _mesh.bbox; + + glBegin(GL_LINE_STRIP); + glVertex3f((float)b.min[0], (float)b.min[1], (float)b.min[2]); + glVertex3f((float)b.max[0], (float)b.min[1], (float)b.min[2]); + glVertex3f((float)b.max[0], (float)b.max[1], (float)b.min[2]); + glVertex3f((float)b.min[0], (float)b.max[1], (float)b.min[2]); + glVertex3f((float)b.min[0], (float)b.min[1], (float)b.min[2]); + glEnd(); + glBegin(GL_LINE_STRIP); + glVertex3f((float)b.min[0], (float)b.min[1], (float)b.max[2]); + glVertex3f((float)b.max[0], (float)b.min[1], (float)b.max[2]); + glVertex3f((float)b.max[0], (float)b.max[1], (float)b.max[2]); + glVertex3f((float)b.min[0], (float)b.max[1], (float)b.max[2]); + glVertex3f((float)b.min[0], (float)b.min[1], (float)b.max[2]); + glEnd(); + glBegin(GL_LINES); + glVertex3f((float)b.min[0], (float)b.min[1], (float)b.min[2]); + glVertex3f((float)b.min[0], (float)b.min[1], (float)b.max[2]); + + glVertex3f((float)b.max[0], (float)b.min[1], (float)b.min[2]); + glVertex3f((float)b.max[0], (float)b.min[1], (float)b.max[2]); + + glVertex3f((float)b.max[0], (float)b.max[1], (float)b.min[2]); + glVertex3f((float)b.max[0], (float)b.max[1], (float)b.max[2]); + + glVertex3f((float)b.min[0], (float)b.max[1], (float)b.min[2]); + glVertex3f((float)b.min[0], (float)b.max[1], (float)b.max[2]); + glEnd(); + } + + void updateClientState(const InternalRendAtts& req) const + { + int ii = 0; + for (typename std::vector::const_iterator it = _bo.begin(); it != _bo.end(); ++it) + { + INT_ATT_NAMES boname(ii); + if ((boname != INT_ATT_NAMES::ATT_VERTINDICES) && (boname != INT_ATT_NAMES::ATT_EDGEINDICES) /*&& (boname != INT_ATT_NAMES::ATT_FIXEDCOLOR)*/) + { + if (req[boname] && _currallocatedboatt[boname] && (*it != NULL)) + { + glBindBuffer((*it)->_target, (*it)->_bohandle); + setBufferPointer(boname); + glEnableClientState((*it)->_clientstatetag); + glBindBuffer((*it)->_target, 0); + } + else + { + glBindBuffer((*it)->_target, (*it)->_bohandle); + disableClientState(boname, req); + glBindBuffer((*it)->_target, 0); + } + } + ++ii; + } + } + + void setBufferPointer(INT_ATT_NAMES boname) const + { + unsigned int ii = boname; + if (ii >= INT_ATT_NAMES::enumArity()) + return; + GLBufferObject* cbo = _bo[ii]; + if (cbo == NULL) + return; + + switch (ii) + { + case(INT_ATT_NAMES::ATT_VERTPOSITION): + { + glVertexPointer(GLint(cbo->_components), cbo->_gltype, GLsizei(0), 0); + break; + } + case(INT_ATT_NAMES::ATT_VERTNORMAL): + case(INT_ATT_NAMES::ATT_FACENORMAL): + { + glNormalPointer(cbo->_gltype, GLsizei(0), 0); + break; + } + case(INT_ATT_NAMES::ATT_VERTCOLOR): + case(INT_ATT_NAMES::ATT_FACECOLOR): + { + glColorPointer(GLint(cbo->_components), cbo->_gltype, GLsizei(0), 0); + break; + } + case(INT_ATT_NAMES::ATT_VERTTEXTURE): + case(INT_ATT_NAMES::ATT_WEDGETEXTURE): + { + glTexCoordPointer(GLint(cbo->_components), cbo->_gltype, GLsizei(0), 0); + break; + } + default: break; + } + } + + void disableClientState(INT_ATT_NAMES boname, const RendAtts& req) const + { + + if (boname >= INT_ATT_NAMES::enumArity()) + return; + + switch (boname) + { + case(INT_ATT_NAMES::ATT_VERTPOSITION): + { + glDisableClientState(GL_VERTEX_ARRAY); + break; + } + case(INT_ATT_NAMES::ATT_VERTNORMAL): + case(INT_ATT_NAMES::ATT_FACENORMAL): + { + if (!req[INT_ATT_NAMES::ATT_VERTNORMAL] && !req[INT_ATT_NAMES::ATT_FACENORMAL]) + glDisableClientState(GL_NORMAL_ARRAY); + break; + } + case(INT_ATT_NAMES::ATT_VERTCOLOR): + case(INT_ATT_NAMES::ATT_FACECOLOR): + { + if (!req[INT_ATT_NAMES::ATT_VERTCOLOR] && !req[INT_ATT_NAMES::ATT_FACECOLOR]) + glDisableClientState(GL_COLOR_ARRAY); + break; + } + case(INT_ATT_NAMES::ATT_VERTTEXTURE): + case(INT_ATT_NAMES::ATT_WEDGETEXTURE): + { + if (!req[INT_ATT_NAMES::ATT_VERTTEXTURE] && !req[INT_ATT_NAMES::ATT_WEDGETEXTURE]) + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + break; + } + default: + { + break; + } + + } + } + + void fillchunkMap() + { + if (!vcg::tri::HasPerWedgeTexCoord(_mesh)) + return; + _chunkmap.clear(); + typename MESH_TYPE::FaceIterator infrange = _mesh.face.begin(); + short texind = std::numeric_limits::max(); + int hh = 0; + for (typename MESH_TYPE::FaceIterator fit = _mesh.face.begin(); fit != _mesh.face.end(); ++fit) + { + if (fit->WT(0).N() != texind) + { + if ((texind != std::numeric_limits::max()) || (fit == _mesh.face.end() - 1)) + { + GLuint lowind = std::distance(_mesh.face.begin(), infrange); + GLuint topind = std::distance(_mesh.face.begin(), fit) - 1; + _chunkmap[texind].push_back(std::make_pair(lowind, topind)); + infrange = fit; + } + texind = fit->WT(0).N(); + } + ++hh; + } + _chunkmap[texind].push_back(std::make_pair(std::distance(_mesh.face.begin(), infrange), std::distance(_mesh.face.begin(), _mesh.face.end() - 1))); + } + + void debug(const InternalRendAtts& tobeallocated, const InternalRendAtts& tobedeallocated, const InternalRendAtts& tobeupdated) + { + _loginfo.reset(); + _loginfo._tobedeallocated = std::string("to_be_deallocated: "); + _loginfo._tobeallocated = std::string("to_be_allocated: "); + _loginfo._tobeupdated = std::string("to_be_updated: "); + + std::string truestring("true"); + std::string falsestring("false"); + for (unsigned int ii = 0; ii < INT_ATT_NAMES::enumArity(); ++ii) + { + std::string deallocres(falsestring); + if (tobedeallocated[ii]) + deallocres = truestring; + _loginfo._tobedeallocated += deallocres + " "; + + std::string allocres(falsestring); + if (tobeallocated[ii]) + allocres = truestring; + _loginfo._tobeallocated += allocres + " "; + + std::string upres(falsestring); + if (tobeupdated[ii]) + upres = truestring; + _loginfo._tobeupdated += upres + " "; + } + + _loginfo._tobedeallocated = std::string("[") + _loginfo._tobedeallocated + std::string("]"); + _loginfo._tobeallocated = std::string("[") + _loginfo._tobeallocated + std::string("]"); + _loginfo._tobeupdated = std::string("[") + _loginfo._tobeupdated + std::string("]"); + + + int hh = 0; + + for (typename ViewsMap::const_iterator it = _perviewreqatts.begin(); it != _perviewreqatts.end(); ++it) + { + std::stringstream tmpstream; + tmpstream << "view_" << hh << ":\n"; + for (size_t pm = 0; pm < size_t(PR_ARITY); ++pm) + { + tmpstream << DebugInfo::primitiveName(pm) << " "; + + for (unsigned int ii = 0; ii < INT_ATT_NAMES::enumArity(); ++ii) + { + std::string res = falsestring; + if (it->second._intatts[pm][ii]) + res = truestring; + tmpstream << "att[" << ii << "]=" << res << " "; + } + tmpstream << std::endl; + } + _loginfo._perviewdata.push_back(tmpstream.str()); + ++hh; + } + + std::stringstream tmpstream; + tmpstream << "currently_allocated: "; + for (unsigned int ii = 0; ii < INT_ATT_NAMES::enumArity(); ++ii) + { + std::string res = falsestring; + if (_currallocatedboatt[ii]) + res = truestring; + tmpstream << "att[" << ii << "]=" << res << " "; + } + _loginfo._currentlyallocated = tmpstream.str(); + } + + class EdgeVertInd + { + public: + + GLuint _v[2]; // the two Vertex indices are ordered! + + EdgeVertInd() {} + EdgeVertInd(const MESH_TYPE& m, typename MESH_TYPE::FacePointer pf, const int nz) { this->set(m, pf, nz); } + EdgeVertInd(const MESH_TYPE& m, typename MESH_TYPE::EdgePointer pe, const int nz) { this->set(m, pe, nz); } + + void set(const MESH_TYPE& m, typename MESH_TYPE::FacePointer pf, const int nz) + { + assert(pf != 0); + assert(nz >= 0); + assert(nz < pf->VN()); + + _v[0] = GLuint(vcg::tri::Index(m, pf->V(nz)));; + _v[1] = GLuint(vcg::tri::Index(m, pf->V(pf->Next(nz)))); + assert(_v[0] != _v[1]); // The face pointed by 'f' is Degenerate (two coincident vertexes) + + if (_v[0] > _v[1]) + std::swap(_v[0], _v[1]); + } + + void set(const MESH_TYPE& m, typename MESH_TYPE::EdgePointer pe, const int nz) + { + assert(pe != 0); + assert(nz >= 0); + assert(nz < 2); + + _v[0] = size_t(vcg::tri::Index(m, pe->V(nz)));; + _v[1] = size_t(vcg::tri::Index(m, pe->V((nz + 1) % 2))); + assert(_v[0] != _v[1]); // The face pointed by 'f' is Degenerate (two coincident vertexes) + + if (_v[0] > _v[1]) + std::swap(_v[0], _v[1]); + } + + inline bool operator<(const EdgeVertInd& pe) const + { + if (_v[0] < pe._v[0]) + return true; + else if (_v[0] > pe._v[0]) + return false; + else + return _v[1] < pe._v[1]; + } + + inline bool operator==(const EdgeVertInd & pe) const + { + return _v[0] == pe._v[0] && _v[1] == pe._v[1]; + } + }; + + static void fillEdgeVector(MESH_TYPE &m, std::vector &edgeVec, bool includeFauxEdge = true) + { + if (m.FN() > 0) + { + edgeVec.reserve(m.FN() * 3); + for (typename MESH_TYPE::FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) + if (!(*fi).IsD()) + for (int j = 0; j < (*fi).VN(); ++j) + if (includeFauxEdge || !(*fi).IsF(j)) + edgeVec.push_back(EdgeVertInd(m, &*fi, j)); + } + else + if ((m.VN() > 0) && (m.EN() > 0)) + { + edgeVec.reserve(m.EN() * 2); + for (typename MESH_TYPE::EdgeIterator ei = m.edge.begin(); ei != m.edge.end(); ++ei) + if (!(*ei).IsD()) + for (int j = 0; j < 2; ++j) + edgeVec.push_back(EdgeVertInd(m, &*ei, j)); + } + + } + + static void fillUniqueEdgeVector(MESH_TYPE &m, std::vector &edgeVec) + { + fillEdgeVector(m, edgeVec, false); + std::sort(edgeVec.begin(), edgeVec.end()); + + typename std::vector::iterator newEnd = std::unique(edgeVec.begin(), edgeVec.end()); + + edgeVec.resize(newEnd - edgeVec.begin()); + } + + struct GLBufferObject + { + GLBufferObject(size_t components, GLenum gltype, GLenum clientstatetag, GLenum target) + :_size(0), _components(components), _isvalid(false), _gltype(gltype), _clientstatetag(clientstatetag), _target(target), _bohandle(0) + { + } + + GLBufferObject(size_t components, GLenum gltype, GLenum target) + :_size(0), _components(components), _isvalid(false), _gltype(gltype), _clientstatetag(), _target(target), _bohandle(0) + { + } + + size_t getSizeOfGLType() const + { + switch (_gltype) + { + case(GL_FLOAT): + return sizeof(GLfloat); + case(GL_INT): + return sizeof(GLint); + case(GL_UNSIGNED_INT): + return sizeof(GLuint); + case(GL_UNSIGNED_BYTE): + return sizeof(GLubyte); + } + return 0; + } + + size_t _size; + const size_t _components; + bool _isvalid; + const GLenum _gltype; + const GLenum _target; + + /*WARNING!!!!!!!!!!!!!!!!! In openGL INDEX BO doesn't require to be enabled/disabled so has NOT a valid tag associated. + In this case the client state tag remains not initialized and it's not meaningful */ + const GLenum _clientstatetag; + /**********************************************************************************/ + + GLuint _bohandle; + }; + + //ideally this should be const. I'm not yet sure if VCGLib will allow me to declare it as constant + MESH_TYPE& _mesh; + + MemoryInfo& _gpumeminfo; + + /*The buffer objects used for the rendering operation. They are shared among all the views*/ + std::vector _bo; + + typedef std::map< UNIQUE_VIEW_ID_TYPE, PVData > ViewsMap; + + ///*_perviewreqatts contains a map of the requested atts by each single view. it's maintained for the actual rendering step*/ + ViewsMap _perviewreqatts; + + /*_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*/ + /* WARNING!!!! The currently allocated BOs are the union of all the BOs requested to be visualized in the _perviewreqatts plus, possibly, the edgeindex bo (depending by the kind of per view render primitive modality that is requested) and the vertexindex bo (depending of the solid rendering modality, per-face/per-vertex)*/ + /* The EdgeIndex bo is allocated only if one of the requested rendering modality is PR_WIREFRAME_EDGES or PR_WIREFRAME_EDGES. If we have PR_SOLID the glPolygonMode function is used for rendering the triangle wireframe view*/ + InternalRendAtts _currallocatedboatt; + + bool _borendering; + size_t _perbatchprim; + + /*Additional structures used for per wedge texturing modality*/ + typedef std::vector< std::pair< GLuint, GLuint > > ChunkVector; + typedef std::map< short, ChunkVector > ChunkMap; + + std::vector< std::pair > _texindnumtriangles; + ChunkMap _chunkmap; + + //Horrible waste of memory space...but computing the list of edges is too much expensive...we must minimize it! + std::vector _edge; + size_t _meshverticeswhenedgeindiceswerecomputed; + size_t _meshtriangleswhenedgeindiceswerecomputed; + + //vcg::GLOptions _glopts; + vcg::Matrix44 _tr; + + bool _debugmode; + DebugInfo _loginfo; + + std::vector _meaningfulattsperprimitive; + }; } #endif diff --git a/wrap/igl/smooth_field.h b/wrap/igl/smooth_field.h index cb421cfa..1cd942d3 100644 --- a/wrap/igl/smooth_field.h +++ b/wrap/igl/smooth_field.h @@ -369,7 +369,7 @@ public: AddBorderConstraints(mesh); //aff final constraints - for (int i=0;i