From a2efddf45661e6fe22bebd8f5f2370aaa2fca458 Mon Sep 17 00:00:00 2001 From: granzuglia Date: Wed, 3 Jun 2015 13:06:35 +0000 Subject: [PATCH] - added new opengl attributes feeder --- wrap/gl/trimesh.h | 3073 ++++++++++++++++++++++++++++++++------------- 1 file changed, 2171 insertions(+), 902 deletions(-) diff --git a/wrap/gl/trimesh.h b/wrap/gl/trimesh.h index 965b4451..3469d8c0 100644 --- a/wrap/gl/trimesh.h +++ b/wrap/gl/trimesh.h @@ -1,902 +1,2171 @@ -/**************************************************************************** -* VCGLib o o * -* Visual and Computer Graphics Library o o * -* _ O _ * -* Copyright(C) 2004 \/)\/ * -* Visual Computing Lab /\/| * -* ISTI - Italian National Research Council | * -* \ * -* All rights reserved. * -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -* This program is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * -* for more details. * -* * -****************************************************************************/ - -#ifndef __VCG_GLTRIMESH -#define __VCG_GLTRIMESH - -#include -#include - -//#include -#include -#include -#include - -namespace vcg { - -template -class GL_TYPE_NM -{public: -static GLenum SCALAR() { assert(0); return 0;} -}; -template <> class GL_TYPE_NM -{ public: -typedef GLfloat ScalarType; -static GLenum SCALAR() { return GL_FLOAT; } -}; -template <> class GL_TYPE_NM -{public: -typedef GLdouble ScalarType; -static GLenum SCALAR() { return GL_DOUBLE; } -}; - -//template <> GL_TYPE::SCALAR() { return GL_DOUBLE; } - -// classe base di glwrap usata solo per poter usare i vari drawmode, normalmode senza dover -// specificare tutto il tipo (a volte lunghissimo) -// della particolare classe glwrap usata. -class GLW -{ -public: - enum DrawMode {DMNone, DMBox, DMPoints, DMWire, DMHidden, DMFlat, DMSmooth, DMFlatWire, DMRadar, DMLast} ; - enum NormalMode {NMNone, NMPerVert, NMPerFace, NMPerWedge, NMLast}; - enum ColorMode {CMNone, CMPerMesh, CMPerFace, CMPerVert, CMLast}; - enum TextureMode{TMNone, TMPerVert, TMPerWedge, TMPerWedgeMulti}; - enum Hint { - HNUseTriStrip = 0x0001, // ha bisogno che ci sia la fftopology gia calcolata! -// HNUseEdgeStrip = 0x0002, // - HNUseDisplayList = 0x0004, - HNCacheDisplayList = 0x0008, // Each mode has its dl; - HNLazyDisplayList = 0x0010, // Display list are generated only when requested - HNIsTwoManifold = 0x0020, // There is no need to make DetachComplex before . - HNUsePerWedgeNormal = 0x0040, // - HNHasFFTopology = 0x0080, // E' l'utente che si preoccupa di tenere aggiornata la topologia ff - HNHasVFTopology = 0x0100, // E' l'utente che si preoccupa di tenere aggiornata la topologia vf - HNHasVertNormal = 0x0200, // E' l'utente che si preoccupa di tenere aggiornata le normali per faccia - HNHasFaceNormal = 0x0400, // E' l'utente che si preoccupa di tenere aggiornata le normali per vertice - HNUseVArray = 0x0800, - HNUseLazyEdgeStrip = 0x1000, // Edge Strip are generated only when requested - HNUseVBO = 0x2000, // Use Vertex Buffer Object - HNIsPolygonal = 0x4000 // In wireframe modes, hide faux edges - }; - - enum Change { - CHVertex = 0x01, - CHNormal = 0x02, - CHColor = 0x04, - CHFace = 0x08, - CHFaceNormal = 0x10, - CHRender = 0x20, - CHAll = 0xff - }; - enum HintParami { - HNPDisplayListSize =0, - HNPPointDistanceAttenuation =1, - HNPPointSmooth = 2 - }; - enum HintParamf { - HNPCreaseAngle =0, // crease angle in radians - HNPZTwist = 1, // Z offset used in Flatwire and hiddenline modality - HNPPointSize = 2 // the point size used in point rendering - }; - - template - class VertToSplit - { - public: - typename MeshType::face_base_pointer f; - char z; - char edge; - bool newp; - typename MeshType::vertex_pointer v; - }; - - // GL Array Elemet - class GLAElem { - public : - int glmode; - int len; - int start; - }; -}; - -template > -class GlTrimesh : public GLW -{ -public: - - typedef typename MeshType::VertexType VertexType; - typedef typename MeshType::FaceType FaceType; - typedef typename MeshType::VertexType::CoordType CoordType; - typedef typename MeshType::VertexType::ScalarType ScalarType; - typedef typename MeshType::VertexIterator VertexIterator; - typedef typename MeshType::EdgeIterator EdgeIterator; - typedef typename MeshType::FaceIterator FaceIterator; - - FACE_POINTER_CONTAINER face_pointers; - - MeshType *m; - unsigned int array_buffers[3]; - - std::vector TMId; - - int curr_hints; // the current hints - - // The parameters of hints - int HNParami[8]; - float HNParamf[8]; - - DrawMode cdm; // Current DrawMode - NormalMode cnm; // Current NormalMode - ColorMode ccm; // Current ColorMode - - static NormalMode convertDrawModeToNormalMode(DrawMode dm) - { - switch(dm) - { - case(DMFlat): - case(DMFlatWire): - case(DMRadar): - return NMPerFace; - case(DMPoints): - case(DMWire): - case(DMSmooth): - return NMPerVert; - default: - return NMNone; - } - return NMNone; - } - - GlTrimesh() - { - m=0; - dl=0xffffffff; - curr_hints=HNUseLazyEdgeStrip; - cdm=DMNone; - ccm=CMNone; - cnm=NMNone; - - SetHintParamf(HNPCreaseAngle,float(M_PI/5)); - SetHintParamf(HNPZTwist,0.00005f); - SetHintParamf(HNPPointSize,1.0f); - SetHintParami(HNPPointDistanceAttenuation, 1); - SetHintParami(HNPPointSmooth, 0); - } - - ~GlTrimesh() - { - //Delete the VBOs - if(curr_hints&HNUseVBO) - { - for(int i=0;i<3;++i) - if(glIsBuffer(GLuint(array_buffers[i]))) - glDeleteBuffersARB(1, (GLuint *)(array_buffers+i)); - } - } - - unsigned int dl; - std::vector indices; - - void SetHintParami(const HintParami hip, const int value) - { - HNParami[hip]=value; - } - int GetHintParami(const HintParami hip) const - { - return HNParami[hip]; - } - void SetHintParamf(const HintParamf hip, const float value) - { - HNParamf[hip]=value; - } - float GetHintParamf(const HintParamf hip) const - { - return HNParamf[hip]; - } - void SetHint(Hint hn) - { - curr_hints |= hn; - } - void ClearHint(Hint hn) - { - curr_hints&=(~hn); - } - -void Update(/*Change c=CHAll*/) -{ - if(m==0) return; - - if(curr_hints&HNUseVArray || curr_hints&HNUseVBO) - { - indices.clear(); - for(FaceIterator fi = m->face.begin(); fi != m->face.end(); ++fi) - { - indices.push_back((unsigned int)((*fi).V(0) - &(*m->vert.begin()))); - indices.push_back((unsigned int)((*fi).V(1) - &(*m->vert.begin()))); - indices.push_back((unsigned int)((*fi).V(2) - &(*m->vert.begin()))); - } - - if(curr_hints&HNUseVBO) - { - if(!glIsBuffer(array_buffers[1])) - glGenBuffers(2,(GLuint*)array_buffers); - glBindBuffer(GL_ARRAY_BUFFER,array_buffers[0]); - glBufferData(GL_ARRAY_BUFFER_ARB, m->vn * sizeof(VertexType), - (char *)&(m->vert[0].P()), GL_STATIC_DRAW_ARB); - - glBindBuffer(GL_ARRAY_BUFFER,array_buffers[1]); - glBufferData(GL_ARRAY_BUFFER_ARB, m->vn * sizeof(VertexType), - (char *)&(m->vert[0].N()), GL_STATIC_DRAW_ARB); - } - - glVertexPointer(3,GL_TYPE_NM::SCALAR(),sizeof(VertexType),0); - glNormalPointer(GL_TYPE_NM::SCALAR(),sizeof(VertexType),0); - } - - //int C=c; - //if((C&CHVertex) || (C&CHFace)) { - // ComputeBBox(*m); - // if(!(curr_hints&HNHasFaceNormal)) m->ComputeFaceNormal(); - // if(!(curr_hints&HNHasVertNormal)) m->ComputeVertexNormal(); - // C= (C | CHFaceNormal); - //} - //if((C&CHFace) && (curr_hints&HNUseEdgeStrip)) ComputeEdges(); - //if((C&CHFace) && (curr_hints&HNUseLazyEdgeStrip)) ClearEdges(); - //if(MeshType::HasFFTopology()) - // if((C&CHFace) && (curr_hints&HNUseTriStrip)) { - // if(!(curr_hints&HNHasFFTopology)) m->FFTopology(); - // ComputeTriStrip(); - // } - //if((C&CHFaceNormal) && (curr_hints&HNUsePerWedgeNormal)) { - // if(!(curr_hints&HNHasVFTopology)) m->VFTopology(); - // CreaseWN(*m,MeshType::scalar_type(GetHintParamf(HNPCreaseAngle))); - //} - //if(C!=0) { // force the recomputation of display list - // cdm=DMNone; - // ccm=CMNone; - // cnm=NMNone; - //} - //if((curr_hints&HNUseVArray) && (curr_hints&HNUseTriStrip)) - // { - // ConvertTriStrip(*m,TStrip,TStripF,TStripVED,TStripVEI); - // } -} - -void Draw(DrawMode dm ,ColorMode cm, TextureMode tm) -{ - switch(dm) - { - case DMNone : Draw(cm,tm); break; - case DMBox : Draw(cm,tm); break; - case DMPoints : Draw(cm,tm); break; - case DMWire : Draw(cm,tm); break; - case DMHidden : Draw(cm,tm); break; - case DMFlat : Draw(cm,tm); break; - case DMSmooth : Draw(cm,tm); break; - case DMFlatWire: Draw(cm,tm); break; - default : break; - } -} - -template< DrawMode dm > -void Draw(ColorMode cm, TextureMode tm) -{ - switch(cm) - { - case CMNone : Draw(tm); break; - case CMPerMesh : Draw(tm); break; - case CMPerFace : Draw(tm); break; - case CMPerVert : Draw(tm); break; - default : break; - } -} - -template< DrawMode dm, ColorMode cm > -void Draw(TextureMode tm) -{ - switch(tm) - { - case TMNone : Draw(); break; - case TMPerVert : Draw(); break; - case TMPerWedge : Draw(); break; - case TMPerWedgeMulti : Draw(); break; - default : break; - } -} - -template< DrawMode dm, ColorMode cm, TextureMode tm> -void Draw() -{ - if(!m) return; - if((curr_hints & HNUseDisplayList)){ - if (cdm==dm && ccm==cm){ - glCallList(dl); - return; - } - else { - if(dl==0xffffffff) dl=glGenLists(1); - glNewList(dl,GL_COMPILE); - } - } - - glPushMatrix(); - switch(dm) - { - case DMNone : break; - case DMBox : DrawBBox(cm);break; - case DMPoints : DrawPoints();break; - case DMHidden : DrawHidden();break; - case DMFlat : DrawFill();break; - case DMFlatWire : DrawFlatWire();break; - case DMRadar : DrawRadar();break; - case DMWire : DrawWire();break; - case DMSmooth : DrawFill();break; - default : break; - } - glPopMatrix(); - - if((curr_hints & HNUseDisplayList)){ - cdm=dm; - ccm=cm; - glEndList(); - glCallList(dl); - } -} - - -/*********************************************************************************************/ -/*********************************************************************************************/ - - -template -void DrawFill() -{ - if(m->fn==0) return; - - if(cm == CMPerMesh) - glColor(m->C()); - - if(tm == TMPerWedge || tm == TMPerWedgeMulti ) - glDisable(GL_TEXTURE_2D); - - if(curr_hints&HNUseVBO) - { - if( (cm==CMNone) || (cm==CMPerMesh) ) - { - if (nm==NMPerVert) - glEnableClientState (GL_NORMAL_ARRAY); - glEnableClientState (GL_VERTEX_ARRAY); - - if (nm==NMPerVert) - { - glBindBuffer(GL_ARRAY_BUFFER,array_buffers[1]); - glNormalPointer(GL_TYPE_NM::SCALAR(),sizeof(typename MeshType::VertexType),0); - } - glBindBuffer(GL_ARRAY_BUFFER,array_buffers[0]); - glVertexPointer(3,GL_TYPE_NM::SCALAR(),sizeof(typename MeshType::VertexType),0); - - glDrawElements(GL_TRIANGLES ,m->fn*3,GL_UNSIGNED_INT, &(*indices.begin()) ); - glDisableClientState (GL_VERTEX_ARRAY); - if (nm==NMPerVert) - glDisableClientState (GL_NORMAL_ARRAY); - - glBindBuffer(GL_ARRAY_BUFFER, 0); - - return; - - } - } - - if(curr_hints&HNUseVArray) - { - if( (cm==CMNone) || (cm==CMPerMesh) ) - { - if (nm==NMPerVert) - glEnableClientState (GL_NORMAL_ARRAY); - glEnableClientState (GL_VERTEX_ARRAY); - - if (nm==NMPerVert) - glNormalPointer(GL_TYPE_NM::SCALAR(),sizeof(typename MeshType::VertexType),&(m->vert.begin()->N()[0])); - glVertexPointer(3,GL_TYPE_NM::SCALAR(),sizeof(typename MeshType::VertexType),&(m->vert.begin()->P()[0])); - - glDrawElements(GL_TRIANGLES ,m->fn*3,GL_UNSIGNED_INT, &(*indices.begin()) ); - glDisableClientState (GL_VERTEX_ARRAY); - if (nm==NMPerVert) - glDisableClientState (GL_NORMAL_ARRAY); - - return; - } - } - else - - if(curr_hints&HNUseTriStrip) - { - //if( (nm==NMPerVert) && ((cm==CMNone) || (cm==CMPerMesh))) - // if(curr_hints&HNUseVArray){ - // glEnableClientState (GL_NORMAL_ARRAY ); - // glNormalPointer(GL_FLOAT,sizeof(MeshType::VertexType),&(m->vert[0].cN())); - // glEnableClientState (GL_VERTEX_ARRAY); - // glVertexPointer(3,GL_FLOAT,sizeof(MeshType::VertexType),&(m->vert[0].cP())); - // std::vector::iterator vi; - // for(vi=TStripVED.begin();vi!=TStripVED.end();++vi) - // glDrawElements(vi->glmode ,vi->len,GL_UNSIGNED_SHORT,&TStripVEI[vi->start] ); - // - // glDisableClientState (GL_NORMAL_ARRAY ); - // glDisableClientState (GL_VERTEX_ARRAY); - // return; - // } - - //std::vector< MeshType::VertexType *>::iterator vi; - //glBegin(GL_TRIANGLE_STRIP); - //if(nm == NMPerFace) fip=TStripF.begin(); - - //for(vi=TStrip.begin();vi!=TStrip.end(); ++vi){ - // if((*vi)){ - // if(nm==NMPerVert) glNormal((*vi)->cN()); - // if(nm==NMPerFace) glNormal((*fip)->cN()); - // glVertex((*vi)->P()); - // } - // else - // { - // glEnd(); - // glBegin(GL_TRIANGLE_STRIP); - // } - // if(nm == NMPerFace) ++fip; - // } - //glEnd(); - } - else - { - typename FACE_POINTER_CONTAINER::iterator fp; - FaceIterator fi; - - short curtexname=-1; - if(partial) - fp = face_pointers.begin(); - else - fi = m->face.begin(); - - if(tm==TMPerWedgeMulti) - { - curtexname=(*fi).WT(0).n(); - if ((curtexname >= 0) && (curtexname < (int)TMId.size())) - { - glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D,TMId[curtexname]); - } - else - { - glDisable(GL_TEXTURE_2D); - } - } - - if(tm==TMPerWedge) - glEnable(GL_TEXTURE_2D); - - if(tm==TMPerVert && !TMId.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,TMId[curtexname]); - } - glBegin(GL_TRIANGLES); - - while( (partial)?(fp!=face_pointers.end()):(fi!=m->face.end())) - { - FaceType & f = (partial)?(*(*fp)): *fi; - - if(!f.IsD()) - { - if(tm==TMPerWedgeMulti) - if(f.WT(0).n() != curtexname) - { - curtexname=(*fi).WT(0).n(); - glEnd(); - - if (curtexname >= 0) - { - glEnable(GL_TEXTURE_2D); - if(!TMId.empty()) - glBindTexture(GL_TEXTURE_2D,TMId[curtexname]); - } - else - { - glDisable(GL_TEXTURE_2D); - } - - glBegin(GL_TRIANGLES); - } - - if(nm == NMPerFace) glNormal(f.cN()); - if(nm == NMPerVert) glNormal(f.V(0)->cN()); - if(nm == NMPerWedge)glNormal(f.WN(0)); - - if(cm == CMPerFace) glColor(f.C()); - if(cm == CMPerVert) glColor(f.V(0)->C()); - if(tm==TMPerVert) glTexCoord(f.V(0)->T().P()); - if( (tm==TMPerWedge)||(tm==TMPerWedgeMulti) )glTexCoord(f.WT(0).t(0)); - glVertex(f.V(0)->P()); - - if(nm == NMPerVert) glNormal(f.V(1)->cN()); - if(nm == NMPerWedge)glNormal(f.WN(1)); - if(cm == CMPerVert) glColor(f.V(1)->C()); - if(tm==TMPerVert) glTexCoord(f.V(1)->T().P()); - if( (tm==TMPerWedge)|| (tm==TMPerWedgeMulti)) glTexCoord(f.WT(1).t(0)); - glVertex(f.V(1)->P()); - - if(nm == NMPerVert) glNormal(f.V(2)->cN()); - if(nm == NMPerWedge)glNormal(f.WN(2)); - if(cm == CMPerVert) glColor(f.V(2)->C()); - if(tm==TMPerVert) glTexCoord(f.V(2)->T().P()); - if( (tm==TMPerWedge)|| (tm==TMPerWedgeMulti)) glTexCoord(f.WT(2).t(0)); - glVertex(f.V(2)->P()); - } - - if(partial) - ++fp; - else - ++fi; - } - - glEnd(); - - } -} - -// A draw wireframe that hides faux edges -template -void DrawWirePolygonal() -{ - if(cm == CMPerMesh) glColor(m->C()); - FaceIterator fi; - typename FACE_POINTER_CONTAINER::iterator fp; - - if(partial) - fp = face_pointers.begin(); - else - fi = m->face.begin(); - - glBegin(GL_LINES); - - while( (partial)?(fp!=face_pointers.end()):(fi!=m->face.end())) - { - typename MeshType::FaceType & f = (partial)?(*(*fp)): *fi; - - if(!f.IsD()) - { - - if(nm == NMPerFace) glNormal(f.cN()); - if(cm == CMPerFace) glColor(f.C()); - - if (!f.IsF(0)) { - if(nm == NMPerVert) glNormal(f.V(0)->cN()); - if(nm == NMPerWedge)glNormal(f.WN(0)); - if(cm == CMPerVert) glColor(f.V(0)->C()); - glVertex(f.V(0)->P()); - - if(nm == NMPerVert) glNormal(f.V(1)->cN()); - if(nm == NMPerWedge)glNormal(f.WN(1)); - if(cm == CMPerVert) glColor(f.V(1)->C()); - glVertex(f.V(1)->P()); - } - - if (!f.IsF(1)) { - if(nm == NMPerVert) glNormal(f.V(1)->cN()); - if(nm == NMPerWedge)glNormal(f.WN(1)); - if(cm == CMPerVert) glColor(f.V(1)->C()); - glVertex(f.V(1)->P()); - - if(nm == NMPerVert) glNormal(f.V(2)->cN()); - if(nm == NMPerWedge)glNormal(f.WN(2)); - if(cm == CMPerVert) glColor(f.V(2)->C()); - glVertex(f.V(2)->P()); - } - - if (!f.IsF(2)) { - if(nm == NMPerVert) glNormal(f.V(2)->cN()); - if(nm == NMPerWedge)glNormal(f.WN(2)); - if(cm == CMPerVert) glColor(f.V(2)->C()); - glVertex(f.V(2)->P()); - - if(nm == NMPerVert) glNormal(f.V(0)->cN()); - if(nm == NMPerWedge)glNormal(f.WN(0)); - if(cm == CMPerVert) glColor(f.V(0)->C()); - glVertex(f.V(0)->P()); - } - - } - - if(partial) - ++fp; - else - ++fi; - } - - glEnd(); -} - -/// Basic Point drawing fucntion -// works also for mesh with deleted vertices -template -void DrawPointsBase() -{ - glBegin(GL_POINTS); - if(cm==CMPerMesh) glColor(m->C()); - - for(VertexIterator vi=m->vert.begin();vi!=m->vert.end();++vi)if(!(*vi).IsD()) - { - if(nm==NMPerVert) glNormal((*vi).cN()); - if(cm==CMPerVert) glColor((*vi).C()); - glVertex((*vi).P()); - } - glEnd(); -} - -/// Utility function that computes in eyespace the current distance between the camera and the center of the bbox of the mesh -double CameraDistance(){ - CoordType res; - Matrix44 mm; - glGetv(GL_MODELVIEW_MATRIX,mm); - CoordType c=m->bbox.Center(); - res=mm*c; - return Norm(res); -} - -template -void DrawPoints() -{ - glPushAttrib(GL_ENABLE_BIT | GL_POINT_BIT); - if(GetHintParami(HNPPointSmooth)>0) glEnable(GL_POINT_SMOOTH); - else glDisable(GL_POINT_SMOOTH); - glPointSize(GetHintParamf(HNPPointSize)); - if(GetHintParami(HNPPointDistanceAttenuation)>0) - { - float camDist = (float)CameraDistance(); - 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 ); - glPointSize(GetHintParamf(HNPPointSize)); - } - - if(m->vn!=(int)m->vert.size()) - { - DrawPointsBase(); - } - else - { - if(cm==CMPerMesh) - glColor(m->C()); - if (m->vert.size() != 0) - { - // Perfect case, no deleted stuff, - // draw the vertices using vertex arrays - if (nm==NMPerVert) - { - glEnableClientState (GL_NORMAL_ARRAY); - glNormalPointer(GL_TYPE_NM::SCALAR(),sizeof(VertexType),&(m->vert.begin()->N()[0])); - } - if (cm==CMPerVert) - { - glEnableClientState (GL_COLOR_ARRAY); - glColorPointer(4,GL_UNSIGNED_BYTE,sizeof(typename MeshType::VertexType),&(m->vert.begin()->C()[0])); - } - - glEnableClientState (GL_VERTEX_ARRAY); - glVertexPointer(3,GL_TYPE_NM::SCALAR(),sizeof(VertexType),&(m->vert.begin()->P()[0])); - - glDrawArrays(GL_POINTS,0,m->vn); - - glDisableClientState (GL_VERTEX_ARRAY); - if (nm==NMPerVert) glDisableClientState (GL_NORMAL_ARRAY); - if (cm==CMPerVert) glDisableClientState (GL_COLOR_ARRAY); - } - } - glPopAttrib(); - return; -} - -void DrawHidden() -{ - //const float ZTWIST=HNParamf[HNPZTwist]; - glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT | GL_LIGHTING_BIT ); - glEnable(GL_POLYGON_OFFSET_FILL); - glPolygonOffset(1.0, 1); - //glDepthRange(ZTWIST,1.0f); - glDisable(GL_LIGHTING); - glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE); - DrawFill(); - glDisable(GL_POLYGON_OFFSET_FILL); - glEnable(GL_LIGHTING); - glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE); - //glDepthRange(0.0f,1.0f-ZTWIST); - DrawWire(); - glPopAttrib(); -// glDepthRange(0,1.0f); -} - -template -void DrawFlatWire() -{ - //const float ZTWIST=HNParamf[HNPZTwist]; - //glDepthRange(ZTWIST,1.0f); - glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT | GL_LIGHTING_BIT ); - glEnable(GL_POLYGON_OFFSET_FILL); - glPolygonOffset(1.0, 1); - DrawFill(); - glDisable(GL_POLYGON_OFFSET_FILL); - //glDepthRange(0.0f,1.0f-ZTWIST); - glEnable(GL_COLOR_MATERIAL); - glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE); - //glColorMaterial(GL_FRONT,GL_DIFFUSE); - glColor3f(.3f,.3f,.3f); - DrawWire(); - glPopAttrib(); - //glDepthRange(0,1.0f); -} - -template -void DrawRadar() -{ - const float ZTWIST=HNParamf[HNPZTwist]; - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glDepthMask(0); - glDepthRange(ZTWIST,1.0f); - - if (cm == CMNone) - glColor4f(0.2f, 1.0f, 0.4f, 0.2f); -// DrawFill(); - Draw(); - - glDepthMask(1); - glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE); -// DrawFill(); - Draw(); - - glDepthRange(0.0f,1.0f-ZTWIST); - glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE); - glColor4f(0.1f, 1.0f, 0.2f, 0.6f); - Draw(); - glDisable(GL_BLEND); - glDepthRange(0,1.0f); - -} - - - -#ifdef GL_TEXTURE0_ARB -// Multitexturing nel caso voglia usare due texture unit. -void DrawTexture_NPV_TPW2() -{ - unsigned int texname=(*(m->face.begin())).WT(0).n(0); - glBindTexture(GL_TEXTURE_2D,TMId[texname]); - typename MeshType::FaceIterator fi; - glBegin(GL_TRIANGLES); - for(fi=m->face.begin();fi!=m->face.end();++fi)if(!(*fi).IsD()){ - if(texname!=(*fi).WT(0).n(0)) { - texname=(*fi).WT(0).n(0); - glEnd(); - glBindTexture(GL_TEXTURE_2D,TMId[texname]); - glBegin(GL_TRIANGLES); - } - glMultiTexCoordARB(GL_TEXTURE0_ARB, (*fi).WT(0).t(0)); - glMultiTexCoordARB(GL_TEXTURE1_ARB, (*fi).WT(0).t(0)); - glNormal((*fi).V(0)->N()); - glVertex((*fi).V(0)->P()); - - glMultiTexCoordARB(GL_TEXTURE0_ARB, (*fi).WT(1).t(0)); - glMultiTexCoordARB(GL_TEXTURE1_ARB, (*fi).WT(1).t(0)); - glNormal((*fi).V(1)->N()); - glVertex((*fi).V(1)->P()); - - glMultiTexCoordARB(GL_TEXTURE0_ARB, (*fi).WT(2).t(0)); - glMultiTexCoordARB(GL_TEXTURE1_ARB, (*fi).WT(2).t(0)); - glNormal((*fi).V(2)->N()); - glVertex((*fi).V(2)->P()); - } - glEnd(); -} - -#endif - - -/*int MemUsed() -{ - int tot=sizeof(GlTrimesh); - tot+=sizeof(mesh_type::edge_type)*edge.size(); - tot+=sizeof(MeshType::VertexType *) * EStrip.size(); - tot+=sizeof(MeshType::VertexType *) * TStrip.size(); - tot+=sizeof(MeshType::FaceType *) * TStripF.size(); - return tot; -}*/ - -private: - -template -void DrawWire() -{ - //if(!(curr_hints & (HNUseEdgeStrip | HNUseLazyEdgeStrip) ) ) - if ( (curr_hints & HNIsPolygonal) ) - { - DrawWirePolygonal(); - } - else - { - glPushAttrib(GL_POLYGON_BIT); - glPolygonMode(GL_FRONT_AND_BACK ,GL_LINE); - DrawFill(); - glPopAttrib(); - } - if(m->fn==0 && m->en>0) - { - glPushAttrib(GL_ENABLE_BIT); - glDisable(GL_LIGHTING); - glBegin(GL_LINES); - for(EdgeIterator ei=m->edge.begin();ei!=m->edge.end(); ++ei) - { - glVertex((*ei).V(0)->P()); - glVertex((*ei).V(1)->P()); - } - glEnd(); - glPopAttrib(); - } - // { -// if(!HasEdges()) ComputeEdges(); - - //if(cm==CMPerMesh) glColor(m->C()); - //std::vector< MeshType::VertexType *>::iterator vi; - //glBegin(GL_LINE_STRIP); - //for(vi=EStrip.begin();vi!=EStrip.end(); ++vi){ - // if((*vi)){ - // glNormal((*vi)->N()); - // glVertex((*vi)->P()); - // } - // else - // { - // glEnd(); - // glBegin(GL_LINE_STRIP); - // } - //} - //glEnd(); - // } -} - -void DrawBBox(ColorMode cm) -{ - if(cm==CMPerMesh) glColor(m->C()); - glBoxWire(m->bbox); -} - - -};// end class - -} // end namespace - - #endif +/**************************************************************************** +* VCGLib o o * +* Visual and Computer Graphics Library o o * +* _ O _ * +* Copyright(C) 2004 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ + +#ifndef __VCG_GLTRIMESH +#define __VCG_GLTRIMESH + +#include +#include +#include +#include +#include + +//#include +#include +#include +#include + + +namespace vcg { + + template + class GL_TYPE_NM + {public: + static GLenum SCALAR() { assert(0); return 0;} + }; + template <> class GL_TYPE_NM + { public: + typedef GLfloat ScalarType; + static GLenum SCALAR() { return GL_FLOAT; } + }; + template <> class GL_TYPE_NM + {public: + typedef GLdouble ScalarType; + static GLenum SCALAR() { return GL_DOUBLE; } + }; + + //template <> GL_TYPE::SCALAR() { return GL_DOUBLE; } + + // classe base di glwrap usata solo per poter usare i vari drawmode, normalmode senza dover + // specificare tutto il tipo (a volte lunghissimo) + // della particolare classe glwrap usata. + class GLW + { + public: + enum DrawMode {DMNone, DMBox, DMPoints, DMWire, DMHidden, DMFlat, DMSmooth, DMFlatWire, DMRadar, DMLast} ; + enum NormalMode {NMNone, NMPerVert, NMPerFace, NMPerWedge, NMLast}; + enum ColorMode {CMNone, CMPerMesh, CMPerFace, CMPerVert, CMLast}; + enum TextureMode{TMNone, TMPerVert, TMPerWedge, TMPerWedgeMulti}; + enum Hint { + HNUseTriStrip = 0x0001, // ha bisogno che ci sia la fftopology gia calcolata! + // HNUseEdgeStrip = 0x0002, // + HNUseDisplayList = 0x0004, + HNCacheDisplayList = 0x0008, // Each mode has its dl; + HNLazyDisplayList = 0x0010, // Display list are generated only when requested + HNIsTwoManifold = 0x0020, // There is no need to make DetachComplex before . + HNUsePerWedgeNormal = 0x0040, // + HNHasFFTopology = 0x0080, // E' l'utente che si preoccupa di tenere aggiornata la topologia ff + HNHasVFTopology = 0x0100, // E' l'utente che si preoccupa di tenere aggiornata la topologia vf + HNHasVertNormal = 0x0200, // E' l'utente che si preoccupa di tenere aggiornata le normali per faccia + HNHasFaceNormal = 0x0400, // E' l'utente che si preoccupa di tenere aggiornata le normali per vertice + HNUseVArray = 0x0800, + HNUseLazyEdgeStrip = 0x1000, // Edge Strip are generated only when requested + HNUseVBO = 0x2000, // Use Vertex Buffer Object + HNIsPolygonal = 0x4000 // In wireframe modes, hide faux edges + }; + + enum Change { + CHVertex = 0x01, + CHNormal = 0x02, + CHColor = 0x04, + CHFace = 0x08, + CHFaceNormal = 0x10, + CHRender = 0x20, + CHAll = 0xff + }; + enum HintParami { + HNPDisplayListSize =0, + HNPPointDistanceAttenuation =1, + HNPPointSmooth = 2 + }; + enum HintParamf { + HNPCreaseAngle =0, // crease angle in radians + HNPZTwist = 1, // Z offset used in Flatwire and hiddenline modality + HNPPointSize = 2 // the point size used in point rendering + }; + + template + class VertToSplit + { + public: + typename MeshType::face_base_pointer f; + char z; + char edge; + bool newp; + typename MeshType::vertex_pointer v; + }; + + // GL Array Elemet + class GLAElem { + public : + int glmode; + int len; + int start; + }; + + std::vector TMId; + }; + + template > + class GlTrimesh : public GLW + { + public: + + typedef typename MeshType::VertexType VertexType; + typedef typename MeshType::FaceType FaceType; + typedef typename MeshType::VertexType::CoordType CoordType; + typedef typename MeshType::VertexType::ScalarType ScalarType; + typedef typename MeshType::VertexIterator VertexIterator; + typedef typename MeshType::EdgeIterator EdgeIterator; + typedef typename MeshType::FaceIterator FaceIterator; + + FACE_POINTER_CONTAINER face_pointers; + + MeshType *m; + unsigned int array_buffers[3]; + + int curr_hints; // the current hints + + // The parameters of hints + int HNParami[8]; + float HNParamf[8]; + + DrawMode cdm; // Current DrawMode + NormalMode cnm; // Current NormalMode + ColorMode ccm; // Current ColorMode + + static NormalMode convertDrawModeToNormalMode(DrawMode dm) + { + switch(dm) + { + case(DMFlat): + case(DMFlatWire): + case(DMRadar): + return NMPerFace; + case(DMPoints): + case(DMWire): + case(DMSmooth): + return NMPerVert; + default: + return NMNone; + } + return NMNone; + } + + GlTrimesh() + { + m=0; + dl=0xffffffff; + curr_hints=HNUseLazyEdgeStrip; + cdm=DMNone; + ccm=CMNone; + cnm=NMNone; + + SetHintParamf(HNPCreaseAngle,float(M_PI/5)); + SetHintParamf(HNPZTwist,0.00005f); + SetHintParamf(HNPPointSize,1.0f); + SetHintParami(HNPPointDistanceAttenuation, 1); + SetHintParami(HNPPointSmooth, 0); + } + + ~GlTrimesh() + { + //Delete the VBOs + if(curr_hints&HNUseVBO) + { + for(int i=0;i<3;++i) + if(glIsBuffer(GLuint(array_buffers[i]))) + glDeleteBuffersARB(1, (GLuint *)(array_buffers+i)); + } + } + + unsigned int dl; + std::vector indices; + + void SetHintParami(const HintParami hip, const int value) + { + HNParami[hip]=value; + } + int GetHintParami(const HintParami hip) const + { + return HNParami[hip]; + } + void SetHintParamf(const HintParamf hip, const float value) + { + HNParamf[hip]=value; + } + float GetHintParamf(const HintParamf hip) const + { + return HNParamf[hip]; + } + void SetHint(Hint hn) + { + curr_hints |= hn; + } + void ClearHint(Hint hn) + { + curr_hints&=(~hn); + } + + void Update(/*Change c=CHAll*/) + { + if(m==0) return; + + if(curr_hints&HNUseVArray || curr_hints&HNUseVBO) + { + indices.clear(); + for(FaceIterator fi = m->face.begin(); fi != m->face.end(); ++fi) + { + indices.push_back((unsigned int)((*fi).V(0) - &(*m->vert.begin()))); + indices.push_back((unsigned int)((*fi).V(1) - &(*m->vert.begin()))); + indices.push_back((unsigned int)((*fi).V(2) - &(*m->vert.begin()))); + } + + if(curr_hints&HNUseVBO) + { + if(!glIsBuffer(array_buffers[1])) + glGenBuffers(2,(GLuint*)array_buffers); + glBindBuffer(GL_ARRAY_BUFFER,array_buffers[0]); + glBufferData(GL_ARRAY_BUFFER_ARB, m->vn * sizeof(VertexType), + (char *)&(m->vert[0].P()), GL_STATIC_DRAW_ARB); + + glBindBuffer(GL_ARRAY_BUFFER,array_buffers[1]); + glBufferData(GL_ARRAY_BUFFER_ARB, m->vn * sizeof(VertexType), + (char *)&(m->vert[0].N()), GL_STATIC_DRAW_ARB); + } + + glVertexPointer(3,GL_TYPE_NM::SCALAR(),sizeof(VertexType),0); + glNormalPointer(GL_TYPE_NM::SCALAR(),sizeof(VertexType),0); + } + + //int C=c; + //if((C&CHVertex) || (C&CHFace)) { + // ComputeBBox(*m); + // if(!(curr_hints&HNHasFaceNormal)) m->ComputeFaceNormal(); + // if(!(curr_hints&HNHasVertNormal)) m->ComputeVertexNormal(); + // C= (C | CHFaceNormal); + //} + //if((C&CHFace) && (curr_hints&HNUseEdgeStrip)) ComputeEdges(); + //if((C&CHFace) && (curr_hints&HNUseLazyEdgeStrip)) ClearEdges(); + //if(MeshType::HasFFTopology()) + // if((C&CHFace) && (curr_hints&HNUseTriStrip)) { + // if(!(curr_hints&HNHasFFTopology)) m->FFTopology(); + // ComputeTriStrip(); + // } + //if((C&CHFaceNormal) && (curr_hints&HNUsePerWedgeNormal)) { + // if(!(curr_hints&HNHasVFTopology)) m->VFTopology(); + // CreaseWN(*m,MeshType::scalar_type(GetHintParamf(HNPCreaseAngle))); + //} + //if(C!=0) { // force the recomputation of display list + // cdm=DMNone; + // ccm=CMNone; + // cnm=NMNone; + //} + //if((curr_hints&HNUseVArray) && (curr_hints&HNUseTriStrip)) + // { + // ConvertTriStrip(*m,TStrip,TStripF,TStripVED,TStripVEI); + // } + } + + void Draw(DrawMode dm ,ColorMode cm, TextureMode tm) + { + switch(dm) + { + case DMNone : Draw(cm,tm); break; + case DMBox : Draw(cm,tm); break; + case DMPoints : Draw(cm,tm); break; + case DMWire : Draw(cm,tm); break; + case DMHidden : Draw(cm,tm); break; + case DMFlat : Draw(cm,tm); break; + case DMSmooth : Draw(cm,tm); break; + case DMFlatWire: Draw(cm,tm); break; + default : break; + } + } + + template< DrawMode dm > + void Draw(ColorMode cm, TextureMode tm) + { + switch(cm) + { + case CMNone : Draw(tm); break; + case CMPerMesh : Draw(tm); break; + case CMPerFace : Draw(tm); break; + case CMPerVert : Draw(tm); break; + default : break; + } + } + + template< DrawMode dm, ColorMode cm > + void Draw(TextureMode tm) + { + switch(tm) + { + case TMNone : Draw(); break; + case TMPerVert : Draw(); break; + case TMPerWedge : Draw(); break; + case TMPerWedgeMulti : Draw(); break; + default : break; + } + } + + template< DrawMode dm, ColorMode cm, TextureMode tm> + void Draw() + { + if(!m) return; + if((curr_hints & HNUseDisplayList)){ + if (cdm==dm && ccm==cm){ + glCallList(dl); + return; + } + else { + if(dl==0xffffffff) dl=glGenLists(1); + glNewList(dl,GL_COMPILE); + } + } + + glPushMatrix(); + switch(dm) + { + case DMNone : break; + case DMBox : DrawBBox(cm);break; + case DMPoints : DrawPoints();break; + case DMHidden : DrawHidden();break; + case DMFlat : DrawFill();break; + case DMFlatWire : DrawFlatWire();break; + case DMRadar : DrawRadar();break; + case DMWire : DrawWire();break; + case DMSmooth : DrawFill();break; + default : break; + } + glPopMatrix(); + + if((curr_hints & HNUseDisplayList)){ + cdm=dm; + ccm=cm; + glEndList(); + glCallList(dl); + } + } + + + /*********************************************************************************************/ + /*********************************************************************************************/ + + + template + void DrawFill() + { + if(m->fn==0) return; + + if(cm == CMPerMesh) + glColor(m->C()); + + if(tm == TMPerWedge || tm == TMPerWedgeMulti ) + glDisable(GL_TEXTURE_2D); + + if(curr_hints&HNUseVBO) + { + if( (cm==CMNone) || (cm==CMPerMesh) ) + { + if (nm==NMPerVert) + glEnableClientState (GL_NORMAL_ARRAY); + glEnableClientState (GL_VERTEX_ARRAY); + + if (nm==NMPerVert) + { + glBindBuffer(GL_ARRAY_BUFFER,array_buffers[1]); + glNormalPointer(GL_TYPE_NM::SCALAR(),sizeof(typename MeshType::VertexType),0); + } + glBindBuffer(GL_ARRAY_BUFFER,array_buffers[0]); + glVertexPointer(3,GL_TYPE_NM::SCALAR(),sizeof(typename MeshType::VertexType),0); + + glDrawElements(GL_TRIANGLES ,m->fn*3,GL_UNSIGNED_INT, &(*indices.begin()) ); + glDisableClientState (GL_VERTEX_ARRAY); + if (nm==NMPerVert) + glDisableClientState (GL_NORMAL_ARRAY); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + + return; + + } + } + + if(curr_hints&HNUseVArray) + { + if( (cm==CMNone) || (cm==CMPerMesh) ) + { + if (nm==NMPerVert) + glEnableClientState (GL_NORMAL_ARRAY); + glEnableClientState (GL_VERTEX_ARRAY); + + if (nm==NMPerVert) + glNormalPointer(GL_TYPE_NM::SCALAR(),sizeof(typename MeshType::VertexType),&(m->vert.begin()->N()[0])); + glVertexPointer(3,GL_TYPE_NM::SCALAR(),sizeof(typename MeshType::VertexType),&(m->vert.begin()->P()[0])); + + glDrawElements(GL_TRIANGLES ,m->fn*3,GL_UNSIGNED_INT, &(*indices.begin()) ); + glDisableClientState (GL_VERTEX_ARRAY); + if (nm==NMPerVert) + glDisableClientState (GL_NORMAL_ARRAY); + + return; + } + } + else + + if(curr_hints&HNUseTriStrip) + { + //if( (nm==NMPerVert) && ((cm==CMNone) || (cm==CMPerMesh))) + // if(curr_hints&HNUseVArray){ + // glEnableClientState (GL_NORMAL_ARRAY ); + // glNormalPointer(GL_FLOAT,sizeof(MeshType::VertexType),&(m->vert[0].cN())); + // glEnableClientState (GL_VERTEX_ARRAY); + // glVertexPointer(3,GL_FLOAT,sizeof(MeshType::VertexType),&(m->vert[0].cP())); + // std::vector::iterator vi; + // for(vi=TStripVED.begin();vi!=TStripVED.end();++vi) + // glDrawElements(vi->glmode ,vi->len,GL_UNSIGNED_SHORT,&TStripVEI[vi->start] ); + // + // glDisableClientState (GL_NORMAL_ARRAY ); + // glDisableClientState (GL_VERTEX_ARRAY); + // return; + // } + + //std::vector< MeshType::VertexType *>::iterator vi; + //glBegin(GL_TRIANGLE_STRIP); + //if(nm == NMPerFace) fip=TStripF.begin(); + + //for(vi=TStrip.begin();vi!=TStrip.end(); ++vi){ + // if((*vi)){ + // if(nm==NMPerVert) glNormal((*vi)->cN()); + // if(nm==NMPerFace) glNormal((*fip)->cN()); + // glVertex((*vi)->P()); + // } + // else + // { + // glEnd(); + // glBegin(GL_TRIANGLE_STRIP); + // } + // if(nm == NMPerFace) ++fip; + // } + //glEnd(); + } + else + { + typename FACE_POINTER_CONTAINER::iterator fp; + FaceIterator fi; + + short curtexname=-1; + if(partial) + fp = face_pointers.begin(); + else + fi = m->face.begin(); + + if(tm==TMPerWedgeMulti) + { + curtexname=(*fi).WT(0).n(); + if ((curtexname >= 0) && (curtexname < (int)TMId.size())) + { + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D,TMId[curtexname]); + } + else + { + glDisable(GL_TEXTURE_2D); + } + } + + if(tm==TMPerWedge) + glEnable(GL_TEXTURE_2D); + + if(tm==TMPerVert && !TMId.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,TMId[curtexname]); + } + glBegin(GL_TRIANGLES); + + while( (partial)?(fp!=face_pointers.end()):(fi!=m->face.end())) + { + FaceType & f = (partial)?(*(*fp)): *fi; + + if(!f.IsD()) + { + if(tm==TMPerWedgeMulti) + if(f.WT(0).n() != curtexname) + { + curtexname=(*fi).WT(0).n(); + glEnd(); + + if (curtexname >= 0) + { + glEnable(GL_TEXTURE_2D); + if(!TMId.empty()) + glBindTexture(GL_TEXTURE_2D,TMId[curtexname]); + } + else + { + glDisable(GL_TEXTURE_2D); + } + + glBegin(GL_TRIANGLES); + } + + if(nm == NMPerFace) glNormal(f.cN()); + if(nm == NMPerVert) glNormal(f.V(0)->cN()); + if(nm == NMPerWedge)glNormal(f.WN(0)); + + if(cm == CMPerFace) glColor(f.C()); + if(cm == CMPerVert) glColor(f.V(0)->C()); + if(tm==TMPerVert) glTexCoord(f.V(0)->T().P()); + if( (tm==TMPerWedge)||(tm==TMPerWedgeMulti) )glTexCoord(f.WT(0).t(0)); + glVertex(f.V(0)->P()); + + if(nm == NMPerVert) glNormal(f.V(1)->cN()); + if(nm == NMPerWedge)glNormal(f.WN(1)); + if(cm == CMPerVert) glColor(f.V(1)->C()); + if(tm==TMPerVert) glTexCoord(f.V(1)->T().P()); + if( (tm==TMPerWedge)|| (tm==TMPerWedgeMulti)) glTexCoord(f.WT(1).t(0)); + glVertex(f.V(1)->P()); + + if(nm == NMPerVert) glNormal(f.V(2)->cN()); + if(nm == NMPerWedge)glNormal(f.WN(2)); + if(cm == CMPerVert) glColor(f.V(2)->C()); + if(tm==TMPerVert) glTexCoord(f.V(2)->T().P()); + if( (tm==TMPerWedge)|| (tm==TMPerWedgeMulti)) glTexCoord(f.WT(2).t(0)); + glVertex(f.V(2)->P()); + } + + if(partial) + ++fp; + else + ++fi; + } + + glEnd(); + + } + } + + // A draw wireframe that hides faux edges + template + void DrawWirePolygonal() + { + if(cm == CMPerMesh) glColor(m->C()); + FaceIterator fi; + typename FACE_POINTER_CONTAINER::iterator fp; + + if(partial) + fp = face_pointers.begin(); + else + fi = m->face.begin(); + + glBegin(GL_LINES); + + while( (partial)?(fp!=face_pointers.end()):(fi!=m->face.end())) + { + typename MeshType::FaceType & f = (partial)?(*(*fp)): *fi; + + if(!f.IsD()) + { + + if(nm == NMPerFace) glNormal(f.cN()); + if(cm == CMPerFace) glColor(f.C()); + + if (!f.IsF(0)) { + if(nm == NMPerVert) glNormal(f.V(0)->cN()); + if(nm == NMPerWedge)glNormal(f.WN(0)); + if(cm == CMPerVert) glColor(f.V(0)->C()); + glVertex(f.V(0)->P()); + + if(nm == NMPerVert) glNormal(f.V(1)->cN()); + if(nm == NMPerWedge)glNormal(f.WN(1)); + if(cm == CMPerVert) glColor(f.V(1)->C()); + glVertex(f.V(1)->P()); + } + + if (!f.IsF(1)) { + if(nm == NMPerVert) glNormal(f.V(1)->cN()); + if(nm == NMPerWedge)glNormal(f.WN(1)); + if(cm == CMPerVert) glColor(f.V(1)->C()); + glVertex(f.V(1)->P()); + + if(nm == NMPerVert) glNormal(f.V(2)->cN()); + if(nm == NMPerWedge)glNormal(f.WN(2)); + if(cm == CMPerVert) glColor(f.V(2)->C()); + glVertex(f.V(2)->P()); + } + + if (!f.IsF(2)) { + if(nm == NMPerVert) glNormal(f.V(2)->cN()); + if(nm == NMPerWedge)glNormal(f.WN(2)); + if(cm == CMPerVert) glColor(f.V(2)->C()); + glVertex(f.V(2)->P()); + + if(nm == NMPerVert) glNormal(f.V(0)->cN()); + if(nm == NMPerWedge)glNormal(f.WN(0)); + if(cm == CMPerVert) glColor(f.V(0)->C()); + glVertex(f.V(0)->P()); + } + + } + + if(partial) + ++fp; + else + ++fi; + } + + glEnd(); + } + + /// Basic Point drawing fucntion + // works also for mesh with deleted vertices + template + void DrawPointsBase() + { + glBegin(GL_POINTS); + if(cm==CMPerMesh) glColor(m->C()); + + for(VertexIterator vi=m->vert.begin();vi!=m->vert.end();++vi)if(!(*vi).IsD()) + { + if(nm==NMPerVert) glNormal((*vi).cN()); + if(cm==CMPerVert) glColor((*vi).C()); + glVertex((*vi).P()); + } + glEnd(); + } + + /// Utility function that computes in eyespace the current distance between the camera and the center of the bbox of the mesh + double CameraDistance(){ + CoordType res; + Matrix44 mm; + glGetv(GL_MODELVIEW_MATRIX,mm); + CoordType c=m->bbox.Center(); + res=mm*c; + return Norm(res); + } + + template + void DrawPoints() + { + glPushAttrib(GL_ENABLE_BIT | GL_POINT_BIT); + if(GetHintParami(HNPPointSmooth)>0) glEnable(GL_POINT_SMOOTH); + else glDisable(GL_POINT_SMOOTH); + glPointSize(GetHintParamf(HNPPointSize)); + if(GetHintParami(HNPPointDistanceAttenuation)>0) + { + float camDist = (float)CameraDistance(); + 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 ); + glPointSize(GetHintParamf(HNPPointSize)); + } + + if(m->vn!=(int)m->vert.size()) + { + DrawPointsBase(); + } + else + { + if(cm==CMPerMesh) + glColor(m->C()); + if (m->vert.size() != 0) + { + // Perfect case, no deleted stuff, + // draw the vertices using vertex arrays + if (nm==NMPerVert) + { + glEnableClientState (GL_NORMAL_ARRAY); + glNormalPointer(GL_TYPE_NM::SCALAR(),sizeof(VertexType),&(m->vert.begin()->N()[0])); + } + if (cm==CMPerVert) + { + glEnableClientState (GL_COLOR_ARRAY); + glColorPointer(4,GL_UNSIGNED_BYTE,sizeof(typename MeshType::VertexType),&(m->vert.begin()->C()[0])); + } + + glEnableClientState (GL_VERTEX_ARRAY); + glVertexPointer(3,GL_TYPE_NM::SCALAR(),sizeof(VertexType),&(m->vert.begin()->P()[0])); + + glDrawArrays(GL_POINTS,0,m->vn); + + glDisableClientState (GL_VERTEX_ARRAY); + if (nm==NMPerVert) glDisableClientState (GL_NORMAL_ARRAY); + if (cm==CMPerVert) glDisableClientState (GL_COLOR_ARRAY); + } + } + glPopAttrib(); + return; + } + + void DrawHidden() + { + //const float ZTWIST=HNParamf[HNPZTwist]; + glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT | GL_LIGHTING_BIT ); + glEnable(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(1.0, 1); + //glDepthRange(ZTWIST,1.0f); + glDisable(GL_LIGHTING); + glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE); + DrawFill(); + glDisable(GL_POLYGON_OFFSET_FILL); + glEnable(GL_LIGHTING); + glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE); + //glDepthRange(0.0f,1.0f-ZTWIST); + DrawWire(); + glPopAttrib(); + // glDepthRange(0,1.0f); + } + + template + void DrawFlatWire() + { + //const float ZTWIST=HNParamf[HNPZTwist]; + //glDepthRange(ZTWIST,1.0f); + glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT | GL_LIGHTING_BIT ); + glEnable(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(1.0, 1); + DrawFill(); + glDisable(GL_POLYGON_OFFSET_FILL); + //glDepthRange(0.0f,1.0f-ZTWIST); + glEnable(GL_COLOR_MATERIAL); + glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE); + //glColorMaterial(GL_FRONT,GL_DIFFUSE); + glColor3f(.3f,.3f,.3f); + DrawWire(); + glPopAttrib(); + //glDepthRange(0,1.0f); + } + + template + void DrawRadar() + { + const float ZTWIST=HNParamf[HNPZTwist]; + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDepthMask(0); + glDepthRange(ZTWIST,1.0f); + + if (cm == CMNone) + glColor4f(0.2f, 1.0f, 0.4f, 0.2f); + // DrawFill(); + Draw(); + + glDepthMask(1); + glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE); + // DrawFill(); + Draw(); + + glDepthRange(0.0f,1.0f-ZTWIST); + glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE); + glColor4f(0.1f, 1.0f, 0.2f, 0.6f); + Draw(); + glDisable(GL_BLEND); + glDepthRange(0,1.0f); + + } + + + +#ifdef GL_TEXTURE0_ARB + // Multitexturing nel caso voglia usare due texture unit. + void DrawTexture_NPV_TPW2() + { + unsigned int texname=(*(m->face.begin())).WT(0).n(0); + glBindTexture(GL_TEXTURE_2D,TMId[texname]); + typename MeshType::FaceIterator fi; + glBegin(GL_TRIANGLES); + for(fi=m->face.begin();fi!=m->face.end();++fi)if(!(*fi).IsD()){ + if(texname!=(*fi).WT(0).n(0)) { + texname=(*fi).WT(0).n(0); + glEnd(); + glBindTexture(GL_TEXTURE_2D,TMId[texname]); + glBegin(GL_TRIANGLES); + } + glMultiTexCoordARB(GL_TEXTURE0_ARB, (*fi).WT(0).t(0)); + glMultiTexCoordARB(GL_TEXTURE1_ARB, (*fi).WT(0).t(0)); + glNormal((*fi).V(0)->N()); + glVertex((*fi).V(0)->P()); + + glMultiTexCoordARB(GL_TEXTURE0_ARB, (*fi).WT(1).t(0)); + glMultiTexCoordARB(GL_TEXTURE1_ARB, (*fi).WT(1).t(0)); + glNormal((*fi).V(1)->N()); + glVertex((*fi).V(1)->P()); + + glMultiTexCoordARB(GL_TEXTURE0_ARB, (*fi).WT(2).t(0)); + glMultiTexCoordARB(GL_TEXTURE1_ARB, (*fi).WT(2).t(0)); + glNormal((*fi).V(2)->N()); + glVertex((*fi).V(2)->P()); + } + glEnd(); + } + +#endif + + + /*int MemUsed() + { + int tot=sizeof(GlTrimesh); + tot+=sizeof(mesh_type::edge_type)*edge.size(); + tot+=sizeof(MeshType::VertexType *) * EStrip.size(); + tot+=sizeof(MeshType::VertexType *) * TStrip.size(); + tot+=sizeof(MeshType::FaceType *) * TStripF.size(); + return tot; + }*/ + + private: + + template + void DrawWire() + { + //if(!(curr_hints & (HNUseEdgeStrip | HNUseLazyEdgeStrip) ) ) + if ( (curr_hints & HNIsPolygonal) ) + { + DrawWirePolygonal(); + } + else + { + glPushAttrib(GL_POLYGON_BIT); + glPolygonMode(GL_FRONT_AND_BACK ,GL_LINE); + DrawFill(); + glPopAttrib(); + } + if(m->fn==0 && m->en>0) + { + glPushAttrib(GL_ENABLE_BIT); + glDisable(GL_LIGHTING); + glBegin(GL_LINES); + for(EdgeIterator ei=m->edge.begin();ei!=m->edge.end(); ++ei) + { + glVertex((*ei).V(0)->P()); + glVertex((*ei).V(1)->P()); + } + glEnd(); + glPopAttrib(); + } + // { + // if(!HasEdges()) ComputeEdges(); + + //if(cm==CMPerMesh) glColor(m->C()); + //std::vector< MeshType::VertexType *>::iterator vi; + //glBegin(GL_LINE_STRIP); + //for(vi=EStrip.begin();vi!=EStrip.end(); ++vi){ + // if((*vi)){ + // glNormal((*vi)->N()); + // glVertex((*vi)->P()); + // } + // else + // { + // glEnd(); + // glBegin(GL_LINE_STRIP); + // } + //} + //glEnd(); + // } + } + + void DrawBBox(ColorMode cm) + { + if(cm==CMPerMesh) glColor(m->C()); + glBoxWire(m->bbox); + } + + + };// end class + + + //WARNING: All the classes derived from MemoryInfo has been intended to be instantiated as a singleton in the host application + //(i.e. in every application using it just an instance of a class derived from MemoryInfo should be declared). + + class MemoryInfo + { + public: + class MemoryInfoException : public std::exception + { + public: + MemoryInfoException(const char* text) + :std::exception(),_exctext(text){} + + ~MemoryInfoException() throw() {} + inline const char* what() const throw() {return _exctext;} + private: + const char* _exctext; + }; + + MemoryInfo(long long unsigned int originalmem) + :_originaltotalmemory(originalmem),_currentfreememory(_originaltotalmemory) + { + } + + virtual ~MemoryInfo() {} + virtual void acquiredMemory(long long unsigned int mem) = 0; + virtual long long unsigned int usedMemory() const = 0; + virtual long long unsigned int currentFreeMemory() const = 0; + virtual void releasedMemory(long long unsigned int mem = 0) = 0; + virtual bool isAdditionalMemoryAvailable(long long unsigned int mem) = 0; + + protected: + const long long unsigned int _originaltotalmemory; + long long unsigned int _currentfreememory; + }; + + //WARNING: this is not a thread safe class. The object derived from MemoryInfo are intended to be used inside GLMeshAttributeFeeder as static variable in order to manage the available GPUMemory. + //We strongly recommend you to define in your code a thread safe version of the class, defining mutexed access member functions. + //This class should be consider just as a basic example for the implementations of the required functionalities. + //It is safe to use it just when the user has only one mesh to pass to the GPU. + + class NotThreadSafeMemoryInfo : public MemoryInfo + { + public: + NotThreadSafeMemoryInfo(long long unsigned int originalmem) + :MemoryInfo(originalmem) + { + } + + ~NotThreadSafeMemoryInfo() {} + + void acquiredMemory(long long unsigned int mem) + { + if (mem > _originaltotalmemory) + throw MemoryInfo::MemoryInfoException("It has been requested more memory than the total one.\\n"); + else + if (mem > _currentfreememory) + throw MemoryInfo::MemoryInfoException("It has been requested more memory than the free available one.\\n"); + else + _currentfreememory -= mem; + } + + long long unsigned int usedMemory() const + { + return _originaltotalmemory - _currentfreememory; + } + + long long unsigned int currentFreeMemory() const + { + return _currentfreememory; + } + + void releasedMemory(long long unsigned int mem = 0) + { + if (mem > _originaltotalmemory) + throw MemoryInfo::MemoryInfoException("It has been released more memory than the total one. Something strange happened!\\n"); + else + _currentfreememory += mem; + } + + bool isAdditionalMemoryAvailable(long long unsigned int mem) + { + return (_currentfreememory >= mem); + } + }; + + struct GLFeedEnum + { + enum MESH_ATTRIBUTE_UPDATED + { + ATT_VERTPOSITION = 0x00000000, + ATT_VERTNORMAL = 0x00000001, + ATT_VERTCOLOR = 0x00000002, + ATT_VERTTEXTURE = 0x00000004, + ATT_FACENORMAL = 0x00000008, + ATT_FACECOLOR = 0x00000010, + ATT_WEDGETEXTURE = 0x00000020, + ATT_ALL = 0xffffffff + }; + + enum COLOR_MODALITY + { + CL_NONE = 0, + CL_PERVERT, + CL_PERFACE, + CL_PERMESH + }; + + enum NORMAL_MODALITY + { + NR_NONE = 0, + NR_PERVERT, + NR_PERFACE + }; + + enum TEXTURE_MODALITY + { + TX_NONE = 0, + TX_PERVERT, + TX_PERWEDGE + }; + }; + + //WARNING! member functions of this class should be called by the host application using concurrency + template + class GLMeshAttributesFeeder : public GLFeedEnum + { + public: + GLMeshAttributesFeeder(/*const*/ MESHTYPE& mesh,MemoryInfo& meminfo, size_t perbatchtriangles = 100) + :_mesh(mesh),_gpumeminfo(meminfo),_bo(8,0),_vaohandle(0),_lastfeedingusedreplicatedpipeline(false),_perbatchsimplex(perbatchtriangles),_chunkmap(),_borendering(false) + { + _bo[VERTPOSITIONBO] = new GLBufferObject(3,GL_FLOAT); + _bo[VERTNORMALBO] = new GLBufferObject(3,GL_FLOAT); + _bo[FACENORMALBO] = new GLBufferObject(3,GL_FLOAT); + _bo[VERTCOLORBO] = new GLBufferObject(4,GL_UNSIGNED_BYTE); + _bo[FACECOLORBO] = new GLBufferObject(4,GL_UNSIGNED_BYTE); + _bo[VERTTEXTUREBO] = new GLBufferObject(2,GL_FLOAT); + _bo[WEDGETEXTUREBO] = new GLBufferObject(2,GL_FLOAT); + _bo[VERTINDEXBO] = new GLBufferObject(3,GL_INT); + } + + ~GLMeshAttributesFeeder() + { + size_t ii = 0; + for(typename std::vector::iterator it = _bo.begin();it != _bo.end();++it) + { + if (*it != NULL) + { + glDeleteBuffers(1,&((*it)->_bohandle)); + (*it)->_bohandle = 0; + } + delete _bo[BO_NAMES(ii)]; + ++ii; + } + _bo.clear(); + glDeleteVertexArrays(1,&_vaohandle); + } + + void setPerBatchTriangles(size_t perbatchtriangles) + { + _perbatchsimplex = perbatchtriangles; + } + + size_t perBatchTriangles() const + { + return _perbatchsimplex; + } + + bool renderedWithBO() const + { + return _borendering; + } + + void update(int mask) + { + if ((mask & ATT_VERTPOSITION) || (mask & ATT_ALL)) + _bo[VERTPOSITIONBO]->_isvalid = false; + + if ((mask & ATT_VERTNORMAL) || (mask & ATT_ALL)) + _bo[VERTNORMALBO]->_isvalid = false; + + if ((mask & ATT_FACENORMAL) || (mask & ATT_ALL)) + _bo[FACENORMALBO]->_isvalid = false; + + if ((mask & ATT_VERTCOLOR) || (mask & ATT_ALL)) + _bo[VERTCOLORBO]->_isvalid = false; + + if ((mask & ATT_FACECOLOR) || (mask & ATT_ALL)) + _bo[FACECOLORBO]->_isvalid = false; + + if ((mask & ATT_VERTTEXTURE) || (mask & ATT_ALL)) + _bo[VERTTEXTUREBO]->_isvalid = false; + + if ((mask & ATT_WEDGETEXTURE) || (mask & ATT_ALL)) + _bo[WEDGETEXTUREBO]->_isvalid = false; + + if (mask & ATT_ALL) + _bo[VERTINDEXBO]->_isvalid = false; + } + + /*WARNING: the passTrianglesToOpenGL & the passPointsToOpenGL functions should be invoked with a reading mutex, + in order to be sure that the referenced mesh would not been changed when the mesh attributes are updated into the buffer objects. + textureindex contained the texture OpenGL ids loaded in the gpu memory by the main application*/ + void passTrianglesToOpenGL(NORMAL_MODALITY nm,COLOR_MODALITY cm,TEXTURE_MODALITY tm,const std::vector& textureindex = std::vector()) + { + std::vector importattribute(_bo.size()); + std::vector attributestobeupdated; + attributesToBeImportedInTriangleBasedPipeline(importattribute, nm, cm, tm); + bool replicated = !importattribute[VERTINDEXBO]; + bool immediatemode = !(buffersAllocationFunction(nm,cm,tm,importattribute,attributestobeupdated)); + if (immediatemode) + immediateMode(nm,cm,tm,textureindex); + else + { + bool somethingtoupdate = false; + for(size_t hh = 0;hh < attributestobeupdated.size();++hh) + somethingtoupdate = somethingtoupdate || attributestobeupdated[hh]; + if (somethingtoupdate) + { + if (replicated) + { + //WARNING!In case we have to update the wedgetexture bo maybe (not always!) we must update also the other buffer already in memory + //cause the wedgetexture pipeline force a change in the order of the triangles in GPU. + //they are now ordered by the texture seam and not more by the triangle index! + if (attributestobeupdated[WEDGETEXTUREBO]) + { + for(size_t jj = 0;jj < attributestobeupdated.size();++jj) + attributestobeupdated[jj] = importattribute[jj] || attributestobeupdated[jj]; + } + updateBuffersReplicatedPipeline(attributestobeupdated,tm); + } + else + updateBuffersIndexedPipeline(attributestobeupdated); + } + drawTriangles(nm,cm,tm,textureindex); + } + + } + + void passPointsToOpenGL(NORMAL_MODALITY nm,COLOR_MODALITY cm) + { + std::vector importattribute(_bo.size()); + std::vector attributestobeupdated; + attributesToBeImportedInPointBasedPipeline(importattribute, nm, cm); + GLenum err = glGetError(); + assert(err == GL_NO_ERROR); + bool immediatemode = !(buffersAllocationFunction(nm,cm,TX_NONE,importattribute,attributestobeupdated)); + err = glGetError(); + assert(err == GL_NO_ERROR); + std::vector textureindex; + if (immediatemode) + immediateMode(nm,cm,TX_NONE,textureindex); + else + { + bool somethingtoupdate = false; + for(size_t hh = 0;hh < attributestobeupdated.size();++hh) + somethingtoupdate = somethingtoupdate || attributestobeupdated[hh]; + if (somethingtoupdate) + { + GLenum err = glGetError(); + assert(err == GL_NO_ERROR); + updateBuffersIndexedPipeline(attributestobeupdated); + err = glGetError(); + assert(err == GL_NO_ERROR); + } + err = glGetError(); + assert(err == GL_NO_ERROR); + drawPoints(nm,cm); + err = glGetError(); + assert(err == GL_NO_ERROR); + } + } + + private: + struct GLBufferObject + { + GLBufferObject(size_t components,GLenum gltype) + :_size(0),_components(components),_isvalid(false),_gltype(gltype),_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; + GLuint _bohandle; + }; + + enum BO_NAMES + { + VERTPOSITIONBO = 0, + VERTNORMALBO = 1, + FACENORMALBO = 2, + VERTCOLORBO = 3, + FACECOLORBO = 4, + VERTTEXTUREBO = 5, + WEDGETEXTUREBO = 6, + VERTINDEXBO = 7 + }; + + long long unsigned int bufferObjectsMemoryRequired(NORMAL_MODALITY nm,COLOR_MODALITY cm,TEXTURE_MODALITY tm,bool generateindex) const + { + bool replicated = (nm == NR_PERFACE) || (cm == CL_PERFACE) || (tm == TX_PERWEDGE); + long long unsigned int result(0); + + result += (long long unsigned int) boExpectedDimension(VERTPOSITIONBO,replicated,generateindex); + if (nm == NR_PERVERT) + result += (long long unsigned int) boExpectedDimension(VERTNORMALBO,replicated,generateindex); + if (nm == NR_PERFACE) + result += (long long unsigned int) boExpectedDimension(FACENORMALBO,replicated,generateindex); + if (cm == CL_PERVERT) + result += (long long unsigned int) boExpectedDimension(VERTCOLORBO,replicated,generateindex); + if (cm == CL_PERFACE) + result += (long long unsigned int) boExpectedDimension(FACECOLORBO,replicated,generateindex); + if (tm == TX_PERVERT) + result += (long long unsigned int) boExpectedDimension(VERTTEXTUREBO,replicated,generateindex); + if (tm == TX_PERWEDGE) + result += (long long unsigned int) boExpectedDimension(WEDGETEXTUREBO,replicated,generateindex); + result += (long long unsigned int) boExpectedDimension(VERTINDEXBO,replicated,generateindex); + return result; + } + + void attributesToBeImportedInTriangleBasedPipeline( std::vector &importattribute, NORMAL_MODALITY nm, COLOR_MODALITY cm, TEXTURE_MODALITY tm ) + { + importattribute[VERTPOSITIONBO] = true; + importattribute[VERTNORMALBO] = vcg::tri::HasPerVertexNormal(_mesh) && (nm == NR_PERVERT); + importattribute[FACENORMALBO] = vcg::tri::HasPerFaceNormal(_mesh) && (nm == NR_PERFACE); + importattribute[VERTCOLORBO] = vcg::tri::HasPerVertexColor(_mesh) && (cm == CL_PERVERT); + importattribute[FACECOLORBO] = vcg::tri::HasPerFaceColor(_mesh) && (cm == CL_PERFACE); + importattribute[VERTTEXTUREBO] = vcg::tri::HasPerVertexTexCoord(_mesh) && (tm == TX_PERVERT); + importattribute[WEDGETEXTUREBO] = vcg::tri::HasPerWedgeTexCoord(_mesh) && (tm == TX_PERWEDGE); + + /*check if the requested attributes are available inside the mesh*/ + if (!importattribute[VERTNORMALBO] && !importattribute[FACENORMALBO]) + nm = NR_NONE; + + if (!importattribute[VERTCOLORBO] && !importattribute[FACECOLORBO]) + cm = CL_NONE; + + if (!importattribute[VERTTEXTUREBO] && !importattribute[WEDGETEXTUREBO]) + tm = TX_NONE; + + bool replicated = (nm == NR_PERFACE) || (cm == CL_PERFACE) || (tm == TX_PERWEDGE); + + importattribute[VERTINDEXBO] = !replicated; + } + + void attributesToBeImportedInPointBasedPipeline( std::vector &importattribute, NORMAL_MODALITY nm, COLOR_MODALITY cm) + { + importattribute[VERTPOSITIONBO] = true; + importattribute[VERTNORMALBO] = vcg::tri::HasPerVertexNormal(_mesh) && (nm == NR_PERVERT); + importattribute[FACENORMALBO] = false; + importattribute[VERTCOLORBO] = vcg::tri::HasPerVertexColor(_mesh) && (cm == CL_PERVERT); + importattribute[FACECOLORBO] = false; + importattribute[VERTTEXTUREBO] = false; + importattribute[WEDGETEXTUREBO] = false; + importattribute[VERTINDEXBO] = false; + } + + bool buffersAllocationFunction(NORMAL_MODALITY nm,COLOR_MODALITY cm,TEXTURE_MODALITY tm,const std::vector& importattribute,std::vector& attributestobeupdated) + { + bool replicated = (importattribute[FACENORMALBO] || importattribute[FACECOLORBO] || importattribute[WEDGETEXTUREBO]); + attributestobeupdated.clear(); + attributestobeupdated.resize(importattribute.size()); + long long unsigned int bomemoryrequiredbymesh = this->bufferObjectsMemoryRequired(nm,cm,tm,importattribute[VERTINDEXBO]); + unsigned int ii = 0; + for(typename std::vector::iterator it = _bo.begin();it != _bo.end();++it) + { + BO_NAMES boname = static_cast(ii); + size_t sz = boExpectedSize(boname,replicated,importattribute[VERTINDEXBO]); + size_t dim = boExpectedDimension(boname,replicated,importattribute[VERTINDEXBO]); + if ((*it != NULL) && ((!(*it)->_isvalid) || + /*if _lastfeedingusedreplicatedpipeline == false means that maybe there are valid per vertex attribute buffer objects that MUST be reallocated anyway cause we have to switch to the replicated attributes pipeline*/ + (replicated && !_lastfeedingusedreplicatedpipeline && (isPerVertexAttribute(boname) || (boname == VERTINDEXBO))) || + /*we switched back from the replicated pipeline to the normal one. All the bos have to be regenerated*/ + (!replicated && _lastfeedingusedreplicatedpipeline) || + /*the buffer object is valid but for same reason the number of cells of the bo don't suit anymore the required size. we have to reallocate the buffer object*/ + (((*it)->_isvalid) && (sz != (*it)->_size))) || + //the buffer is valid, but the attribute is not required to be displayed + (((*it)->_isvalid) && !importattribute[ii])) + { + + //disableClientState(boname,importattribute); + + /*WARNING! THIS CODE MUST BE INCAPSULATED INTO A DEALLOCATE FUNCTION IN A PROPER MADE BUFFER OBJECT CLASS + I DON'T INSERT IT INTO THE GLBufferObjectInfo CLASS CAUSE I CONSIDER IT A TEMPORARY PRIVATE STRUCT*/ + glDeleteBuffers(1,&((*it)->_bohandle)); + (*it)->_bohandle = 0; + if ((*it)->_size > 0) + //we don't use dim cause dim is the value that is going to be allocated, instead use (*it)->_size * (*it)->getSizeOfGLType() is the value already in the buffer + _gpumeminfo.releasedMemory((*it)->_size * (*it)->getSizeOfGLType()); + (*it)->_isvalid = false; + (*it)->_size = 0; + /**********************************************************************************************************/ + } + //there are already valid mesh attributes properly allocated in memory, we don't need to allocate them again + if ((*it != NULL) && (((*it)->_isvalid) && (sz == (*it)->_size))) + bomemoryrequiredbymesh -= dim; + ++ii; + } + + if (!_gpumeminfo.isAdditionalMemoryAvailable(bomemoryrequiredbymesh)) + { + std::cout << "no additional memory available!!! memory required: " << bomemoryrequiredbymesh << std::endl; + ii = 0; + for(typename std::vector::iterator it = _bo.begin();it != _bo.end();++it) + { + BO_NAMES boname = static_cast(ii); + size_t sz(boExpectedSize(boname,replicated,importattribute[VERTINDEXBO])); + //there are already valid mesh attributes properly allocated in memory but there is not enough gpu memory for the remaining mesh. + //we have to deallocate the previously allocated mesh attributes + if ((*it != NULL) && (((*it)->_isvalid) && (sz == (*it)->_size))) + { + long long unsigned int dim(boExpectedDimension(boname,replicated,importattribute[VERTINDEXBO])); + //disableClientState(boname,importattribute); + if ((*it)->_size > 0) + { + + + /*WARNING! THIS CODE MUST BE INCAPSULATED INTO A DEALLOCATE FUNCTION IN A PROPER MADE BUFFER OBJECT CLASS + I DON'T INSERT IT INTO THE GLBufferObjectInfo CLASS CAUSE I CONSIDER IT A TEMPORARY PRIVATE STRUCT*/ + glDeleteBuffers(1,&(*it)->_bohandle); + (*it)->_bohandle = 0; + _gpumeminfo.releasedMemory(dim); + } + (*it)->_isvalid = false; + (*it)->_size = 0; + /*********************************************************************************************************/ + } + ++ii; + } + _borendering = false; + _lastfeedingusedreplicatedpipeline = false; + return false; + } + else + { + unsigned int ii = 0; + //I have to update the invalid buffers requested to be imported + attributestobeupdated = importattribute; + for(typename std::vector::iterator it = _bo.begin();it != _bo.end();++it) + { + BO_NAMES boname = static_cast(ii); + GLBufferObject* cbo = _bo.at(boname); + bool importatt = importattribute.at(boname); + GLenum target = GL_ARRAY_BUFFER; + if (boname == VERTINDEXBO) + target = GL_ELEMENT_ARRAY_BUFFER; + + glBindVertexArray(_vaohandle); + bool notvalidbuttoberegenerated = (cbo != NULL) && (!cbo->_isvalid) && (importatt); + if (notvalidbuttoberegenerated) + { + cbo->_size = boExpectedSize(boname,replicated,importattribute[VERTINDEXBO]); + long long unsigned int dim = boExpectedDimension(boname,replicated,importattribute[VERTINDEXBO]); + glGenBuffers(1, &cbo->_bohandle); + glBindBuffer(target, cbo->_bohandle); + glBufferData(target, dim, NULL, GL_STATIC_DRAW); + setBufferPointerEnableClientState(boname); + glBindBuffer(target, 0); + _gpumeminfo.acquiredMemory(dim); + attributestobeupdated[boname] = true; + cbo->_isvalid = true; + } + else + { + attributestobeupdated[boname] = false; + if (!importatt) + cbo->_isvalid = false; + } + + if ((cbo == NULL) || (!cbo->_isvalid)) + { + //glBindVertexArray(_vaohandle); + disableClientState(boname,importattribute); + //glBindVertexArray(0); + } + ++ii; + glBindVertexArray(0); + } + _borendering = true; + _lastfeedingusedreplicatedpipeline = replicated; + return true; + } + } + + bool updateBuffersIndexedPipeline(const std::vector& attributestobeupdated) + { + _chunkmap.clear(); + size_t vn = _mesh.vn; + size_t tn = _mesh.fn; + + size_t facechunk = std::min(size_t(tn),_perbatchsimplex); + size_t vertexchunk = std::min(size_t(vn),_perbatchsimplex); + + std::vector pv(vertexchunk); + std::vector nv(vertexchunk); + std::vector cv(vertexchunk); // Per vertex Colors + std::vector tv(vertexchunk * 2); + + size_t chunckingpu = 0; + + for(size_t i=0;i_bohandle); + glBufferSubData(GL_ARRAY_BUFFER,chunckingpu * vertexchunk * buffobj->_components * buffobj->getSizeOfGLType(),buffobj->_components * buffobj->getSizeOfGLType() * chuncksize,&pv[0]); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } + if (attributestobeupdated[VERTNORMALBO]) + { + GLBufferObject* buffobj = _bo[VERTNORMALBO]; + glBindBuffer(GL_ARRAY_BUFFER, buffobj->_bohandle); + glBufferSubData(GL_ARRAY_BUFFER,chunckingpu * vertexchunk * buffobj->_components * buffobj->getSizeOfGLType(),buffobj->_components * buffobj->getSizeOfGLType() * chuncksize,&nv[0]); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } + if (attributestobeupdated[VERTCOLORBO]) + { + GLBufferObject* buffobj = _bo[VERTCOLORBO]; + glBindBuffer(GL_ARRAY_BUFFER, buffobj->_bohandle); + glBufferSubData(GL_ARRAY_BUFFER,chunckingpu * vertexchunk * buffobj->_components * buffobj->getSizeOfGLType(),buffobj->_components * buffobj->getSizeOfGLType() * chuncksize,&cv[0]); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } + if (attributestobeupdated[VERTTEXTUREBO]) + { + GLBufferObject* buffobj = _bo[VERTTEXTUREBO]; + glBindBuffer(GL_ARRAY_BUFFER, buffobj->_bohandle); + glBufferSubData(GL_ARRAY_BUFFER,chunckingpu * vertexchunk * buffobj->_components * buffobj->getSizeOfGLType(),buffobj->_components * buffobj->getSizeOfGLType() * chuncksize,&tv[0]); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } + + ++chunckingpu; + } + } + + pv.clear(); + nv.clear(); + cv.clear(); + tv.clear(); + + chunckingpu = 0; + std::vector ti(facechunk * 3); + for(size_t i=0;i_bohandle); + glBufferSubData(GL_ELEMENT_ARRAY_BUFFER,chunckingpu * facechunk * _bo[VERTINDEXBO]->_components * _bo[VERTINDEXBO]->getSizeOfGLType(),_bo[VERTINDEXBO]->_components * _bo[VERTINDEXBO]->getSizeOfGLType() * chunksize,&ti[0]); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + } + ++chunckingpu; + } + } + return true; + } + + bool updateBuffersReplicatedPipeline(const std::vector& attributestobeupdated,GLFeedEnum::TEXTURE_MODALITY currtextmod) + { + size_t vn = _mesh.vn; + size_t tn = _mesh.fn; + + size_t facechunk = std::min(size_t(tn),_perbatchsimplex); + + std::vector rpv(facechunk * 3); + std::vector rnv(facechunk * 3); + std::vector rcv(facechunk * 3); + std::vector rtv(facechunk * 3 * 2); + + size_t chunckingpu = 0; + + //it's a map containing for each texture seams n a vector of all the triangle index ranges having n has texture seam + //Suppose that in a mesh we have + //TXS_0{t0,t1,t2,t3}, TXS_4{t4,t5},TXS_0{t6},TXS_-1{t7,t8,t9},TXS_4{t10,t11} + //so chunkMap will contain + // -1 -> [] + // 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[WEDGETEXTUREBO] || attributestobeupdated[VERTTEXTUREBO]) + { + _chunkmap.clear(); + if (attributestobeupdated[WEDGETEXTUREBO]) + fillChunckMap(_chunkmap); + else + if(attributestobeupdated[VERTTEXTUREBO]) + _chunkmap[0].push_back(std::make_pair(0,tn-1)); + } + + //default case: no texture is required to be rendered but a non texture attribute has to be updated + //we have to init the _chunkmap with just one entry (-1...that means no texture) referring all the triangles in the mesh + if ((currtextmod == GLFeedEnum::TX_NONE) && + (attributestobeupdated[VERTPOSITIONBO] || + attributestobeupdated[VERTNORMALBO] || attributestobeupdated[FACENORMALBO] || + attributestobeupdated[VERTCOLORBO] || attributestobeupdated[FACECOLORBO])) + { + _chunkmap.clear(); + _chunkmap[-1].push_back(std::make_pair(0,tn-1)); + } + + int t = 0; + if (attributestobeupdated[WEDGETEXTUREBO] || attributestobeupdated[VERTTEXTUREBO]) + { + _texindnumtriangles.clear(); + _texindnumtriangles.resize(_chunkmap.size()); + } + int i = 0; + size_t chunkindex = i; + GLuint triangles = 0; + for(ChunkMap::const_iterator mit = _chunkmap.begin();mit != _chunkmap.end();++mit) + { + for (ChunkVector::const_iterator cit = mit->second.begin();cit != mit->second.end();++cit) + { + for(size_t indf = cit->first;indf<=cit->second;++indf) + { + chunkindex = i % facechunk; + if (attributestobeupdated[VERTPOSITIONBO]) + { + rpv[chunkindex*3+0].Import(_mesh.face[indf].V(0)->P()); + rpv[chunkindex*3+1].Import(_mesh.face[indf].V(1)->P()); + rpv[chunkindex*3+2].Import(_mesh.face[indf].V(2)->P()); + } + if (attributestobeupdated[VERTNORMALBO]) + { + rnv[chunkindex*3+0].Import(_mesh.face[indf].V(0)->N().Normalize()); + rnv[chunkindex*3+1].Import(_mesh.face[indf].V(1)->N().Normalize()); + rnv[chunkindex*3+2].Import(_mesh.face[indf].V(2)->N().Normalize()); + } + else if (attributestobeupdated[FACENORMALBO]) + { + rnv[chunkindex*3+0].Import(_mesh.face[indf].N().Normalize()); + rnv[chunkindex*3+1].Import(_mesh.face[indf].N().Normalize()); + rnv[chunkindex*3+2].Import(_mesh.face[indf].N().Normalize()); + } + + if ((attributestobeupdated[VERTCOLORBO])) + { + rcv[chunkindex*3+0] = _mesh.face[indf].V(0)->C(); + rcv[chunkindex*3+1] = _mesh.face[indf].V(1)->C(); + rcv[chunkindex*3+2] = _mesh.face[indf].V(2)->C(); + } + else if ((attributestobeupdated[FACECOLORBO])) + { + rcv[chunkindex*3+0] = _mesh.face[indf].C(); + rcv[chunkindex*3+1] = _mesh.face[indf].C(); + rcv[chunkindex*3+2] = _mesh.face[indf].C(); + } + + if (attributestobeupdated[WEDGETEXTUREBO]) + { + rtv[chunkindex*6+0]=float(_mesh.face[indf].WT(0).U()); + rtv[chunkindex*6+1]=float(_mesh.face[indf].WT(0).V()); + rtv[chunkindex*6+2]=float(_mesh.face[indf].WT(1).U()); + rtv[chunkindex*6+3]=float(_mesh.face[indf].WT(1).V()); + rtv[chunkindex*6+4]=float(_mesh.face[indf].WT(2).U()); + rtv[chunkindex*6+5]=float(_mesh.face[indf].WT(2).V()); + } + else if (attributestobeupdated[VERTTEXTUREBO]) + { + rtv[chunkindex*6+0]=float(_mesh.face[indf].V(0)->T().U()); + rtv[chunkindex*6+1]=float(_mesh.face[indf].V(0)->T().V()); + rtv[chunkindex*6+2]=float(_mesh.face[indf].V(1)->T().U()); + rtv[chunkindex*6+3]=float(_mesh.face[indf].V(1)->T().V()); + rtv[chunkindex*6+4]=float(_mesh.face[indf].V(2)->T().U()); + rtv[chunkindex*6+5]=float(_mesh.face[indf].V(2)->T().V()); + } + + if((i == tn - 1) || (chunkindex == facechunk - 1)) + { + size_t chunksize = facechunk; + if (i == tn - 1) + chunksize = chunkindex + 1; + + if (attributestobeupdated[VERTPOSITIONBO]) + { + GLBufferObject* buffobj = _bo[VERTPOSITIONBO]; + glBindBuffer(GL_ARRAY_BUFFER, buffobj->_bohandle); + glBufferSubData(GL_ARRAY_BUFFER,chunckingpu * facechunk * 3 * buffobj->_components * buffobj->getSizeOfGLType(),3 * buffobj->_components * buffobj->getSizeOfGLType() * chunksize,&rpv[0]); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } + if (attributestobeupdated[VERTNORMALBO] || attributestobeupdated[FACENORMALBO]) + { + GLBufferObject* buffobj; + if (attributestobeupdated[VERTNORMALBO]) + buffobj = _bo[VERTNORMALBO]; + else + buffobj = _bo[FACENORMALBO]; + glBindBuffer(GL_ARRAY_BUFFER, buffobj->_bohandle); + glBufferSubData(GL_ARRAY_BUFFER,chunckingpu * facechunk * 3 * buffobj->_components * buffobj->getSizeOfGLType(),3 * buffobj->_components * buffobj->getSizeOfGLType() * chunksize,&rnv[0]); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } + if (attributestobeupdated[VERTCOLORBO] || attributestobeupdated[FACECOLORBO]) + { + GLBufferObject* buffobj; + if (attributestobeupdated[VERTCOLORBO]) + buffobj = _bo[VERTCOLORBO]; + else + buffobj = _bo[FACECOLORBO]; + glBindBuffer(GL_ARRAY_BUFFER, buffobj->_bohandle); + glBufferSubData(GL_ARRAY_BUFFER,chunckingpu * facechunk * 3 *buffobj->_components * buffobj->getSizeOfGLType(),3 * buffobj->_components * buffobj->getSizeOfGLType() * chunksize,&rcv[0]); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } + if (attributestobeupdated[VERTTEXTUREBO] || attributestobeupdated[WEDGETEXTUREBO]) + { + GLBufferObject* buffobj; + if (attributestobeupdated[VERTTEXTUREBO]) + buffobj = _bo[VERTTEXTUREBO]; + else + buffobj = _bo[WEDGETEXTUREBO]; + glBindBuffer(GL_ARRAY_BUFFER, buffobj->_bohandle); + glBufferSubData(GL_ARRAY_BUFFER,chunckingpu * facechunk * 3 *buffobj->_components * buffobj->getSizeOfGLType(),3 * buffobj->_components * buffobj->getSizeOfGLType() * chunksize,&rtv[0]); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } + + ++chunckingpu; + } + ++i; + } + triangles += cit->second - cit->first + 1; + } + + if (attributestobeupdated[WEDGETEXTUREBO] || attributestobeupdated[VERTTEXTUREBO]) + _texindnumtriangles[t] = std::make_pair(mit->first,triangles); + ++t; + } + + //return (k != tn) + // throw MeshLabException("Mesh has not been properly partitioned"); + return true; + } + + bool immediateMode(NORMAL_MODALITY nm,COLOR_MODALITY cm,TEXTURE_MODALITY tm,const std::vector& textureindex) + { + glPushAttrib(GL_ALL_ATTRIB_BITS); + if(_mesh.fn==0) + return false; + + if(cm == CL_PERMESH) + glColor(_mesh.C()); + + //typename MESHTYPE::FaceContainer::iterator fp; + typename MESHTYPE::FaceIterator fi = _mesh.face.begin(); + + short curtexname=-1; + if(tm == TX_PERWEDGE) + { + curtexname=(*fi).WT(0).n(); + if ((curtexname >= 0) && (curtexname < (int)textureindex.size())) + { + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D,textureindex[curtexname]); + } + else + { + glDisable(GL_TEXTURE_2D); + } + } + + if(tm==TX_PERVERT && !textureindex.empty()) // in the case of per vertex tex coord we assume that we have a SINGLE texture. + { + curtexname = 0; + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D,textureindex[curtexname]); + } + + glBegin(GL_TRIANGLES); + + while(fi!=_mesh.face.end()) + { + typename MESHTYPE::FaceType & f = *fi; + if(!f.IsD()) + { + if(tm==TX_PERWEDGE) + if(f.WT(0).n() != curtexname) + { + curtexname=(*fi).WT(0).n(); + glEnd(); + + if (curtexname >= 0) + { + glEnable(GL_TEXTURE_2D); + if(!textureindex.empty()) + glBindTexture(GL_TEXTURE_2D,textureindex[curtexname]); + } + else + { + glDisable(GL_TEXTURE_2D); + } + + glBegin(GL_TRIANGLES); + } + + if(nm == NR_PERFACE) glNormal(f.cN()); + if(nm == NR_PERVERT) glNormal(f.V(0)->cN()); + //if(nm == NMPerWedge)glNormal(f.WN(0)); + + if(cm == CL_PERFACE) glColor(f.C()); + if(cm == CL_PERVERT) glColor(f.V(0)->C()); + if(tm == TX_PERVERT) glTexCoord(f.V(0)->T().P()); + if(tm == TX_PERWEDGE) glTexCoord(f.WT(0).t(0)); + glVertex(f.V(0)->P()); + + if(nm == NR_PERVERT) glNormal(f.V(1)->cN()); + //if(nm == NMPerWedge)glNormal(f.WN(1)); + if(cm == CL_PERVERT) glColor(f.V(1)->C()); + if(tm==TX_PERVERT) glTexCoord(f.V(1)->T().P()); + if(tm==TX_PERWEDGE) glTexCoord(f.WT(1).t(0)); + glVertex(f.V(1)->P()); + + if(nm == NR_PERVERT) glNormal(f.V(2)->cN()); + //if(nm == NMPerWedge)glNormal(f.WN(2)); + if(cm == CL_PERVERT) glColor(f.V(2)->C()); + if(tm==TX_PERVERT) glTexCoord(f.V(2)->T().P()); + if(tm==TX_PERWEDGE) glTexCoord(f.WT(2).t(0)); + glVertex(f.V(2)->P()); + } + ++fi; + } + + glEnd(); + glPopMatrix(); + glPopAttrib(); + return true; + } + + bool drawTriangles(NORMAL_MODALITY nm,COLOR_MODALITY cm,TEXTURE_MODALITY tm,const std::vector& textureindex) + { + std::vector att(_bo.size(),false); + attributesToBeImportedInTriangleBasedPipeline(att,nm,cm,tm); + bool replicated = !att[VERTINDEXBO]; + glBindVertexArray(_vaohandle); + + if (replicated) + { + int firsttriangleoffset = 0; + if(tm == GLFeedEnum::TX_NONE) + { + glDisable(GL_TEXTURE_2D); + glDrawArrays(GL_TRIANGLES,0,_mesh.fn * 3); + } + else + { + glEnable(GL_TEXTURE_2D); + for(std::vector< std::pair >::const_iterator it = _texindnumtriangles.begin();it != _texindnumtriangles.end();++it) + { + if ((it->first != -1) && (it->first < textureindex.size())) + glBindTexture(GL_TEXTURE_2D,textureindex[it->first]); + else + glBindTexture(GL_TEXTURE_2D,0); + glDrawArrays(GL_TRIANGLES,firsttriangleoffset,it->second * 3 - firsttriangleoffset); + firsttriangleoffset = it->second * 3; + } + glBindTexture(GL_TEXTURE_2D,0); + glDisable(GL_TEXTURE_2D); + } + + } + else + { + if(tm==TX_PERVERT) + { + if (textureindex.size() > 0) + { + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D,textureindex[0]); + + } + } + else + glDisable(GL_TEXTURE_2D); + + + if (_bo[VERTINDEXBO]->_isvalid) + { + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,_bo[VERTINDEXBO]->_bohandle); + glDrawElements( GL_TRIANGLES, _mesh.fn * _bo[VERTINDEXBO]->_components,GL_UNSIGNED_INT ,NULL); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + } + + glBindTexture(GL_TEXTURE_2D,0); + glDisable(GL_TEXTURE_2D); + } + glBindVertexArray(0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0); + glBindBuffer(GL_ARRAY_BUFFER,0); + + return true; + } + + void drawPoints(NORMAL_MODALITY nm,COLOR_MODALITY cm) + { + glDisable(GL_TEXTURE_2D); + + glBindVertexArray(_vaohandle); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _bo[VERTINDEXBO]->_bohandle); + glDrawArrays(GL_POINTS,0,_mesh.vn); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glBindVertexArray(0); + } + + void setBufferPointerEnableClientState( BO_NAMES boname) + { + if ((boname < VERTPOSITIONBO) || (boname > VERTINDEXBO)) + return; + GLBufferObject* cbo = _bo[boname]; + if (cbo == NULL) + return; + + switch(boname) + { + case(VERTPOSITIONBO): + { + glVertexPointer(cbo->_components, cbo->_gltype, 0, 0); + glEnableClientState(GL_VERTEX_ARRAY); + break; + } + case(VERTNORMALBO): + case(FACENORMALBO): + { + glNormalPointer(cbo->_gltype, 0, 0); + glEnableClientState(GL_NORMAL_ARRAY); + break; + } + case(VERTCOLORBO): + case(FACECOLORBO): + { + glColorPointer(cbo->_components, cbo->_gltype, 0, 0); + glEnableClientState(GL_COLOR_ARRAY); + break; + } + case(VERTTEXTUREBO): + case(WEDGETEXTUREBO): + { + glTexCoordPointer(cbo->_components, cbo->_gltype, 0, 0); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + break; + } + case(VERTINDEXBO): + { + glIndexPointer(cbo->_gltype, 0, 0); + glEnableClientState(GL_INDEX_ARRAY); + break; + } + } + } + + void disableClientState( BO_NAMES boname,const std::vector& importatt) + { + if ((boname < VERTPOSITIONBO) || (boname > VERTINDEXBO)) + return; + + switch(boname) + { + case(VERTPOSITIONBO): + { + glDisableClientState(GL_VERTEX_ARRAY); + break; + } + case(VERTNORMALBO): + case(FACENORMALBO): + { + if (!importatt[VERTNORMALBO] && !importatt[FACENORMALBO]) + glDisableClientState(GL_NORMAL_ARRAY); + break; + } + case(VERTCOLORBO): + case(FACECOLORBO): + { + if (!importatt[VERTCOLORBO] && !importatt[FACECOLORBO]) + glDisableClientState(GL_COLOR_ARRAY); + break; + } + case(VERTTEXTUREBO): + case(WEDGETEXTUREBO): + { + if (!importatt[VERTTEXTUREBO] && !importatt[WEDGETEXTUREBO]) + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + break; + } + case(VERTINDEXBO): + { + glDisableClientState(GL_INDEX_ARRAY); + break; + } + } + } + + //expected number of cells should have a the named bo + //generateindex is true when i have a triangle based mesh + // is false when i have a point based mesh + size_t boExpectedSize(BO_NAMES name,bool replicatedpipeline,bool generateindex) const + { + try + { + GLBufferObject& cbo = *_bo.at(name); + size_t vertnum(_mesh.VN()); + size_t facenum(_mesh.FN()); + + switch(name) + { + case(VERTPOSITIONBO): + case(VERTNORMALBO): + case(VERTCOLORBO): + case(VERTTEXTUREBO): + { + if (replicatedpipeline) + return facenum * 3 * cbo._components; + else + return vertnum * cbo._components; + } + + case(FACENORMALBO): + case(FACECOLORBO): + case(WEDGETEXTUREBO): + { + if (replicatedpipeline) + return facenum * 3 * cbo._components; + else + return 0; + } + case(VERTINDEXBO): + { + if (replicatedpipeline || !generateindex) + return 0; + else + return facenum * cbo._components; + } + } + } + catch(std::out_of_range& /*exc*/) + { + return 0; + } + return 0; + } + + //generateindex is true when i have a triangle based mesh + // is false when i have a point based mesh + size_t boExpectedDimension(BO_NAMES name,bool replicatedpipeline,bool generateindex) const + { + try + { + size_t sz = boExpectedSize(name,replicatedpipeline,generateindex); + GLBufferObject& cbo = *_bo.at(name); + return sz * cbo.getSizeOfGLType(); + } + catch(std::out_of_range& /*exc*/) + { + return 0; + } + return 0; + } + + static bool isPerVertexAttribute(BO_NAMES name) + { + return ((name == VERTPOSITIONBO) ||(name == VERTNORMALBO) || (name == VERTCOLORBO) || (name == VERTTEXTUREBO)); + } + + //it's a map containing for each texture seams n a vector of all the triangle index ranges having n has texture seam + //Suppose that in a mesh we have + //TXS_0{t0,t1,t2,t3}, TXS_4{t4,t5},TXS_0{t6},TXS_-1{t7,t8,t9},TXS_4{t10,t11} + //so chunkMap will contain + // -1 -> [] + // 0 -> [,] + // 4 -> [,] + + typedef std::vector< std::pair< GLuint,GLuint > > ChunkVector; + typedef std::map< short, ChunkVector > ChunkMap; + + void fillChunckMap(ChunkMap& cmap) + { + if (!vcg::tri::HasPerWedgeTexCoord(_mesh)) + return; + cmap.clear(); + typename MESHTYPE::FaceIterator infrange = _mesh.face.begin(); + short texind = std::numeric_limits::max(); + int hh = 0; + for(typename MESHTYPE::FaceIterator fit = _mesh.face.begin();fit != _mesh.face.end();++fit) + { + if (fit->WT(0).N() != texind) + { + if ((texind != std::numeric_limits::max()) || (fit == _mesh.face.end() - 1)) + { + GLuint lowind = std::distance(_mesh.face.begin(),infrange); + GLuint topind = std::distance(_mesh.face.begin(),fit) - 1; + cmap[texind].push_back(std::make_pair(lowind,topind)); + infrange = fit; + } + texind = fit->WT(0).N(); + } + ++hh; + } + cmap[texind].push_back(std::make_pair(std::distance(_mesh.face.begin(),infrange),std::distance(_mesh.face.begin(),_mesh.face.end() - 1))); + } + + //ideally this should be const. I'm not yet sure if VCGLib will allow me to declare it as constant + MESHTYPE& _mesh; + MemoryInfo& _gpumeminfo; + + std::vector _bo; + GLuint _vaohandle; + std::vector< std::pair > _texindnumtriangles; + + bool _lastfeedingusedreplicatedpipeline; + bool _borendering; + size_t _perbatchsimplex; + ChunkMap _chunkmap; + }; + + template + class SceneToBeRendered + { + public: + SceneToBeRendered(MemoryInfo& gpumeminfo,bool highprecision,size_t perbatchtriangles = 100) + :_scene(),_gpumeminfo(gpumeminfo),_perbatchtriangles(perbatchtriangles),_globalscenecenter(),_highprecision(highprecision) + { + } + + ~SceneToBeRendered() + { + _scene.clear(); + } + + void insert(MESHTYPE* mesh,const vcg::Matrix44& transfmat) + { + MatrixedFeeder matfeed = std::make_pair(transfmat,GLMeshAttributesFeeder(*mesh,_gpumeminfo,_perbatchtriangles)); + _scene[mesh] = matfeed; + if (_highprecision) + computeSceneGlobalCenter(); + } + + void remove(MESHTYPE* mesh) + { + std::map< MESHTYPE*, MatrixedFeeder >::iterator it = _scene.find(mesh); + if (it != _scene.end()) + _scene.erase(it); + } + + void update(MESHTYPE* mesh,int mask) + { + std::map< MESHTYPE*, MatrixedFeeder >::iterator it = _scene.find(mesh); + if (it != _scene.end()) + it->second._feeder.update(mask); + } + + void passTrianglesToOpenGL(MESHTYPE* mesh,GLFeedEnum::NORMAL_MODALITY nm,GLFeedEnum::COLOR_MODALITY cm,GLFeedEnum::TEXTURE_MODALITY tm,const std::vector& textureindex = std::vector()) + { + std::map::iterator it = _scene.find(mesh); + if(it == _scene.end()) + return; + glPushAttrib(GL_TRANSFORM_BIT); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + if (_highprecision) + { + vcg::glMultMatrix(it->second._localmeshmatrix); + vcg::glTranslate(_globalscenecenter); + } + it->second._feeder.passTrianglesToOpenGL(nm,cm,tm,textureindex); + glPopMatrix(); + glPushAttrib(); + } + + void passPointsToOpenGL(MESHTYPE* mesh,GLFeedEnum::NORMAL_MODALITY nm,GLFeedEnum::COLOR_MODALITY cm) + { + std::map::iterator it = _scene.find(mesh); + if(it == _scene.end()) + return; + glPushAttrib(GL_TRANSFORM_BIT); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + if (_highprecision) + { + vcg::glMultMatrix(it->second._localmeshmatrix); + vcg::glTranslate(_globalscenecenter); + } + it->second._feeder.passPointsToOpenGL(nm,cm); + glPopMatrix(); + glPushAttrib(); + } + + private: + struct MatrixedFeeder + { + vcg::Matrix44 _localmeshmatrix; + GLMeshAttributesFeeder _feeder; + + MatrixedFeeder(const vcg::Matrix44& localmeshmatrix,GLMeshAttributesFeeder& feeder) + :_localmeshmatrix(localmeshmatrix),_feeder(feeder) + { + } + }; + + void computeSceneGlobalCenter() + { + vcg::Box3 scenebbox; + for(std::map::const_iterator it = _scene.begin();it != _scene.end();++it) + scenebbox.Add(it->first->bbox,it->second._localmeshmatrix); + + _globalscenecenter = -scenebbox.Center(); + } + + std::map< MESHTYPE*, MatrixedFeeder > _scene; + MemoryInfo& _gpumeminfo; + size_t _perbatchtriangles; + vcg::Point3 _globalscenecenter; + bool _highprecision; + }; + +} // end namespace + +#endif