1 /****************************************************************************
2 * VCGLib                                                            o o     *
3 * Visual and Computer Graphics Library                            o     o   *
4 *                                                                _   O  _   *
5 * Copyright(C) 2004-2016                                           \/)\/    *
6 * Visual Computing Lab                                            /\/|      *
7 * ISTI - Italian National Research Council                           |      *
8 *                                                                    \      *
9 * All rights reserved.                                                      *
10 *                                                                           *
11 * This program is free software; you can redistribute it and/or modify      *
12 * it under the terms of the GNU General Public License as published by      *
13 * the Free Software Foundation; either version 2 of the License, or         *
14 * (at your option) any later version.                                       *
15 *                                                                           *
16 * This program is distributed in the hope that it will be useful,           *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of            *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
19 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt)          *
20 * for more details.                                                         *
21 *                                                                           *
22 ****************************************************************************/
23 
24 #ifndef __VCG_GL_MESH_ATTRIBUTES_FEEDER
25 #define __VCG_GL_MESH_ATTRIBUTES_FEEDER
26 
27 #include <vector>
28 #include <map>
29 #include <algorithm>
30 #include <stdexcept>
31 #include <climits>
32 #include <string>
33 
34 #include <wrap/gl/space.h>
35 #include <wrap/gl/math.h>
36 #include <vcg/space/color4.h>
37 #include <vcg/math/matrix44.h>
38 #include<wrap/system/memory_info.h>
39 #include <wrap/gl/gl_mesh_attributes_info.h>
40 
41 
42 namespace vcg
43 {
44 	struct RenderingModalityGLOptions
45 	{
46 		bool _perbbox_enabled;
47 
48 		bool _perbbox_fixed_color_enabled;
49 		bool _perpoint_fixed_color_enabled;
50 		bool _perwire_fixed_color_enabled;
51 		bool _persolid_fixed_color_enabled;
52 
53 		Color4b _perbbox_fixed_color;
54 		Color4b _perpoint_fixed_color;
55 		Color4b _perwire_fixed_color;
56 		Color4b _persolid_fixed_color;
57 
58 		bool _perbbox_mesh_color_enabled;
59 		bool _perpoint_mesh_color_enabled;
60 		bool _perwire_mesh_color_enabled;
61 		bool _persolid_mesh_color_enabled;
62 
63 		bool _perpoint_noshading;
64 		bool _perwire_noshading;
65 		bool _persolid_noshading;
66 
67 		bool _perpoint_dot_enabled;
68 
69 		float _perpoint_pointsize;
70 		bool _perpoint_pointsmooth_enabled;
71 		bool _perpoint_pointattenuation_enabled;
72 
73 		float _perwire_wirewidth;
74 
RenderingModalityGLOptionsRenderingModalityGLOptions75 		RenderingModalityGLOptions()
76 		{
77 			_perbbox_enabled = false;
78 
79 			_perbbox_fixed_color_enabled = true;
80 			_perpoint_fixed_color_enabled = false;
81 			_perwire_fixed_color_enabled = true;
82 			_persolid_fixed_color_enabled = true;
83 
84 			_perbbox_fixed_color = vcg::Color4b(Color4b::White);
85 			_perpoint_fixed_color = vcg::Color4b(Color4b::White);
86 			_perwire_fixed_color = Color4b(Color4b::DarkGray);
87 			_persolid_fixed_color = vcg::Color4b(Color4b::White);
88 
89 			_perbbox_mesh_color_enabled = false;
90 			_perpoint_mesh_color_enabled = false;
91 			_perwire_mesh_color_enabled = false;
92 			_persolid_mesh_color_enabled = false;
93 
94 			_perpoint_dot_enabled = false;
95 
96 			_perpoint_noshading = false;
97 			_perwire_noshading = true;
98 			_persolid_noshading = false;
99 
100 			_perpoint_pointsize = 3.0f;
101 			_perpoint_pointsmooth_enabled = false;
102 			_perpoint_pointattenuation_enabled = true;
103 			_perwire_wirewidth = 1.0f;
104 		}
105 
RenderingModalityGLOptionsRenderingModalityGLOptions106 		RenderingModalityGLOptions(const RenderingModalityGLOptions& opts)
107 		{
108 			copyData(opts);
109 		}
110 
~RenderingModalityGLOptionsRenderingModalityGLOptions111 		virtual ~RenderingModalityGLOptions()
112 		{
113 		}
114 
115 		RenderingModalityGLOptions& operator=(const RenderingModalityGLOptions& opts)
116 		{
117 			copyData(opts);
118 			return (*this);
119 		}
120 
121 	private:
copyDataRenderingModalityGLOptions122 		void copyData(const RenderingModalityGLOptions& opts)
123 		{
124 			_perbbox_enabled = opts._perbbox_enabled;
125 
126 			_perpoint_dot_enabled = opts._perpoint_dot_enabled;
127 			_perpoint_pointsize = opts._perpoint_pointsize;
128 			_perpoint_pointsmooth_enabled = opts._perpoint_pointsmooth_enabled;
129 			_perpoint_pointattenuation_enabled = opts._perpoint_pointattenuation_enabled;
130 
131 			_perbbox_fixed_color_enabled = opts._perbbox_fixed_color_enabled;
132 			_perpoint_fixed_color_enabled = opts._perpoint_fixed_color_enabled;
133 			_perwire_fixed_color_enabled = opts._perwire_fixed_color_enabled;
134 			_persolid_fixed_color_enabled = opts._persolid_fixed_color_enabled;
135 
136 			_perbbox_mesh_color_enabled = opts._perbbox_mesh_color_enabled;
137 			_perpoint_mesh_color_enabled = opts._perpoint_mesh_color_enabled;
138 			_perwire_mesh_color_enabled = opts._perwire_mesh_color_enabled;
139 			_persolid_mesh_color_enabled = opts._persolid_mesh_color_enabled;
140 
141 			_perbbox_fixed_color = opts._perbbox_fixed_color;
142 			_perpoint_fixed_color = opts._perpoint_fixed_color;
143 			_perwire_fixed_color = opts._perwire_fixed_color;
144 			_persolid_fixed_color = opts._persolid_fixed_color;
145 
146 			_perpoint_noshading = opts._perpoint_noshading;
147 			_perwire_noshading = opts._perwire_noshading;
148 			_persolid_noshading = opts._persolid_noshading;
149 
150 			_perwire_wirewidth = opts._perwire_wirewidth;
151 		}
152 	};
153 
154 	template<typename GL_OPTIONS_DERIVED_TYPE = RenderingModalityGLOptions>
155 	class PerViewData : public GLMeshAttributesInfo
156 	{
157 	public:
158 
159 		typedef GL_OPTIONS_DERIVED_TYPE GLOptionsType;
160 
PerViewData()161 		PerViewData()
162 			:_pmmask(), _intatts(PR_ARITY), _glopts(NULL)
163 		{
164 			reset();
165 		}
166 
167 
PerViewData(const PerViewData<GL_OPTIONS_DERIVED_TYPE> & dt)168 		PerViewData(const PerViewData<GL_OPTIONS_DERIVED_TYPE>& dt)
169 			:_pmmask(dt._pmmask), _intatts(dt._intatts), _glopts(NULL)
170 		{
171 			if (dt._glopts != NULL)
172 				_glopts = new GL_OPTIONS_DERIVED_TYPE(*(dt._glopts));
173 		}
174 
~PerViewData()175 		~PerViewData()
176 		{
177 			_intatts.clear();
178 			delete _glopts;
179 		}
180 
181 		PerViewData& operator=(const PerViewData<GL_OPTIONS_DERIVED_TYPE>& dt)
182 		{
183 			_pmmask = dt._pmmask;
184 			_intatts = dt._intatts;
185 			if (dt._glopts != NULL)
186 				_glopts = new GL_OPTIONS_DERIVED_TYPE(*(dt._glopts));
187 			return (*this);
188 		}
189 
set(PRIMITIVE_MODALITY pm,const RendAtts & atts)190 		bool set(PRIMITIVE_MODALITY pm, const RendAtts& atts)
191 		{
192 			size_t pmind(pm);
193 			if (pm >= _intatts.size())
194 				return false;
195 			//_pmmask.set(pm);
196 			_intatts[pmind] = InternalRendAtts(atts, pm);
197 			_pmmask.set(size_t(pm), _intatts[pmind][INT_ATT_NAMES::ATT_VERTPOSITION]);
198 			return true;
199 		}
200 
set(PRIMITIVE_MODALITY pm,ATT_NAMES att,bool onoff)201 		bool set(PRIMITIVE_MODALITY pm, ATT_NAMES att, bool onoff)
202 		{
203 			size_t pmind(pm);
204 			if (pm >= _intatts.size())
205 				return false;
206 			_intatts[pmind][att] = onoff;
207 			_pmmask.set(size_t(pm), _intatts[pmind][INT_ATT_NAMES::ATT_VERTPOSITION]);
208 			if (_pmmask.test(size_t(pm)))
209 				_intatts[pmind].setIndexingIfNeeded(pm);
210 			return true;
211 		}
212 
set(PRIMITIVE_MODALITY pm,bool onoff)213 		bool set(PRIMITIVE_MODALITY pm, bool onoff)
214 		{
215 			return set(pm, INT_ATT_NAMES::ATT_VERTPOSITION, onoff);
216 		}
217 
set(const GL_OPTIONS_DERIVED_TYPE & opts)218 		void set(const GL_OPTIONS_DERIVED_TYPE& opts)
219 		{
220 			delete _glopts;
221 			_glopts = new GL_OPTIONS_DERIVED_TYPE(opts);
222 		}
223 
isPrimitiveActive(PRIMITIVE_MODALITY pm)224 		bool isPrimitiveActive(PRIMITIVE_MODALITY pm) const
225 		{
226 			if (pm == PR_ARITY)
227 				return false;
228 			return (_pmmask.test(pm) && _intatts[size_t(pm)][INT_ATT_NAMES::ATT_VERTPOSITION]);
229 		}
230 
getPrimitiveModalityMask()231 		PRIMITIVE_MODALITY_MASK getPrimitiveModalityMask() const
232 		{
233 			return _pmmask;
234 		}
235 
get(PRIMITIVE_MODALITY pm,RendAtts & atts)236 		bool get(PRIMITIVE_MODALITY pm, RendAtts& atts) const
237 		{
238 			size_t pmind(pm);
239 			if (pm >= _intatts.size())
240 				return false;
241 			atts = _intatts[pmind];
242 			return true;
243 		}
244 
get(GL_OPTIONS_DERIVED_TYPE & opts)245 		bool get(GL_OPTIONS_DERIVED_TYPE& opts) const
246 		{
247 			if (_glopts == NULL)
248 				return false;
249 			opts = (*_glopts);
250 			return true;
251 		}
252 
253 		void reset(bool deleteglopts = true)
254 		{
255 			_pmmask.reset();
256 			for (typename PerRendModData::iterator it = _intatts.begin(); it != _intatts.end(); ++it)
257 				it->reset();
258 			if (deleteglopts)
259 			{
260 				delete _glopts;
261 				_glopts = 0;
262 			}
263 		}
264 
265 
serialize(std::string & str)266 		void serialize(std::string& str) const
267 		{
268 			str.append(_pmmask.to_string());
269 			for (typename PerRendModData::const_iterator it = _intatts.begin(); it != _intatts.end(); ++it)
270 			{
271 				std::string s;
272 				it->serialize(s);
273 				str.append(s);
274 			}
275 			std::string s;
276 			_glopts->serialize(s);
277 			str.append(s);
278 		}
279 
deserialize(const std::string & str)280 		bool deserialize(const std::string& str)
281 		{
282 			std::string::size_type pos = 0;
283 			std::string token[6];
284 			token[0] = str.substr(pos, _pmmask.size());
285 			if (token[0].length() < _pmmask.size())
286 				return false;
287 			int i = 1;
288 			pos = _pmmask.size();
289 			for (typename PerRendModData::iterator it = _intatts.begin(); it != _intatts.end(); ++it, i++)
290 			{
291 				token[i] = str.substr(pos, InternalRendAtts::AttName::enumArity());
292 				if (token[i].length() < InternalRendAtts::AttName::enumArity())
293 					return false;
294 				pos = pos + InternalRendAtts::AttName::enumArity();
295 			}
296 			if (_glopts != NULL)
297 			{
298 				std::string tmp;
299 				size_t size = _glopts->serialize(tmp);
300 				token[i] = str.substr(pos, size);
301 				if (token[i].length() < size)
302 					return false;
303 			}
304 			_pmmask = PRIMITIVE_MODALITY_MASK(token[0]);
305 			i = 1;
306 			for (typename PerRendModData::iterator it = _intatts.begin(); it != _intatts.end(); ++it, i++)
307 				it->deserialize(token[i]);
308 			if (_glopts != NULL)
309 				_glopts->deserialize(token[i]);
310 			return true;
311 		}
312 
313 	protected:
314 		template<typename MESH_TYPE, typename UNIQUE_VIEW_ID_TYPE, typename XX_GL_OPTIONS_DERIVED_TYPE> friend class NotThreadSafeGLMeshAttributesMultiViewerBOManager;
315 
316 		typedef std::vector<InternalRendAtts> PerRendModData;
317 
318 		PRIMITIVE_MODALITY_MASK _pmmask;
319 		PerRendModData _intatts;
320 
321 		GL_OPTIONS_DERIVED_TYPE* _glopts;
322 	};
323 
324 	/****************************************************WARNING!!!!!!!!!!!!!!!!!*********************************************************************************************/
325 	//You must inherit from NotThreadSafeGLMeshAttributesMultiViewerBOManager, providing thread safe mechanisms, in order to use the bo facilities exposed by the class.
326 	//In wrap/qt/qt_thread_safe_memory_rendering.h you will find a ready to use class based on QtConcurrency module.
327 	/*************************************************************************************************************************************************************************/
328 	template<typename MESH_TYPE, typename UNIQUE_VIEW_ID_TYPE = unsigned int, typename GL_OPTIONS_DERIVED_TYPE = RenderingModalityGLOptions>
329 	class NotThreadSafeGLMeshAttributesMultiViewerBOManager : public GLMeshAttributesInfo
330 	{
331 	public:
332 		typedef PerViewData<GL_OPTIONS_DERIVED_TYPE> PVData;
333 
334 	protected:
335 		/****************************************************WARNING!!!!!!!!!!!!!!!!!*********************************************************************************************/
336 		//You must inherit from NotThreadSafeGLMeshAttributesMultiViewerBOManager, providing thread safe mechanisms, in order to use the bo facilities exposed by the class.
337 		//In wrap/qt/qt_thread_safe_memory_rendering.h you will find a ready to use class based on QtConcurrency module.
338 		/*************************************************************************************************************************************************************************/
339 
NotThreadSafeGLMeshAttributesMultiViewerBOManager(MESH_TYPE & mesh,MemoryInfo & meminfo,size_t perbatchprimitives)340 		NotThreadSafeGLMeshAttributesMultiViewerBOManager(/*const*/ MESH_TYPE& mesh, MemoryInfo& meminfo, size_t perbatchprimitives)
341 			:_mesh(mesh), _gpumeminfo(meminfo), _bo(INT_ATT_NAMES::enumArity(), NULL), _currallocatedboatt(), _borendering(false), _perbatchprim(perbatchprimitives), _chunkmap(),  _edge(), _meshverticeswhenedgeindiceswerecomputed(0), _meshtriangleswhenedgeindiceswerecomputed(0), _tr(), _debugmode(false), _loginfo(), _meaningfulattsperprimitive(PR_ARITY, InternalRendAtts())
342 		{
343 			_tr.SetIdentity();
344 			_bo[INT_ATT_NAMES::ATT_VERTPOSITION] = new GLBufferObject(3, GL_FLOAT, GL_VERTEX_ARRAY, GL_ARRAY_BUFFER);
345 			_bo[INT_ATT_NAMES::ATT_VERTNORMAL] = new GLBufferObject(3, GL_FLOAT, GL_NORMAL_ARRAY, GL_ARRAY_BUFFER);
346 			_bo[INT_ATT_NAMES::ATT_FACENORMAL] = new GLBufferObject(3, GL_FLOAT, GL_NORMAL_ARRAY, GL_ARRAY_BUFFER);
347 			_bo[INT_ATT_NAMES::ATT_VERTCOLOR] = new GLBufferObject(4, GL_UNSIGNED_BYTE, GL_COLOR_ARRAY, GL_ARRAY_BUFFER);
348 			_bo[INT_ATT_NAMES::ATT_FACECOLOR] = new GLBufferObject(4, GL_UNSIGNED_BYTE, GL_COLOR_ARRAY, GL_ARRAY_BUFFER);
349 			/*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*/
350 			//_bo[INT_ATT_NAMES::ATT_FIXEDCOLOR] = NULL;
351 			_bo[INT_ATT_NAMES::ATT_VERTTEXTURE] = new GLBufferObject(2, GL_FLOAT, GL_TEXTURE_COORD_ARRAY, GL_ARRAY_BUFFER);
352 			_bo[INT_ATT_NAMES::ATT_WEDGETEXTURE] = new GLBufferObject(2, GL_FLOAT, GL_TEXTURE_COORD_ARRAY, GL_ARRAY_BUFFER);
353 			_bo[INT_ATT_NAMES::ATT_VERTINDICES] = new GLBufferObject(3, GL_UNSIGNED_INT, GL_ELEMENT_ARRAY_BUFFER);
354 			_bo[INT_ATT_NAMES::ATT_EDGEINDICES] = new GLBufferObject(2, GL_UNSIGNED_INT, GL_ELEMENT_ARRAY_BUFFER);
355 
356 			initMeaningfulAttsMask();
357 		}
358 
359 
~NotThreadSafeGLMeshAttributesMultiViewerBOManager()360 		~NotThreadSafeGLMeshAttributesMultiViewerBOManager()
361 		{
362 			_edge.clear();
363 			for (size_t ii = 0; ii < _bo.size(); ++ii)
364 				delete _bo[ii];
365 			_bo.clear();
366 		}
367 
368 		/*MeshAttributesUpdate will force the buffer allocation only of the bo rendered at least by one viewer. */
369 		/*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*/
370 		/*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. */
meshAttributesUpdated(bool hasmeshconnectivitychanged,const RendAtts & changedrendatts)371 		void meshAttributesUpdated(bool hasmeshconnectivitychanged, const RendAtts& changedrendatts)
372 		{
373 			InternalRendAtts tobeupdated(changedrendatts);
374 			tobeupdated[INT_ATT_NAMES::ATT_VERTINDICES] = hasmeshconnectivitychanged;
375 			tobeupdated[INT_ATT_NAMES::ATT_EDGEINDICES] = hasmeshconnectivitychanged;
376 			for (unsigned int ii = 0; ii < INT_ATT_NAMES::enumArity(); ++ii)
377 			{
378 				INT_ATT_NAMES boname(ii);
379 				if (_bo[boname] != NULL)
380 					_bo[boname]->_isvalid = (_bo[boname]->_isvalid) && !(tobeupdated[boname]);
381 			}
382 		}
383 
getPerViewInfo(UNIQUE_VIEW_ID_TYPE viewid,PVData & data)384 		bool getPerViewInfo(UNIQUE_VIEW_ID_TYPE viewid, PVData& data) const
385 		{
386 			typename ViewsMap::const_iterator it = _perviewreqatts.find(viewid);
387 			if (it == _perviewreqatts.end())
388 				return false;
389 			data = it->second;
390 			return true;
391 		}
392 
setPerViewInfo(UNIQUE_VIEW_ID_TYPE viewid,const PVData & data)393 		void setPerViewInfo(UNIQUE_VIEW_ID_TYPE viewid, const PVData& data)
394 		{
395 			///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
396 			PVData copydt(data);
397 			for (PRIMITIVE_MODALITY pm = PRIMITIVE_MODALITY(0); pm < PR_ARITY; pm = next(pm))
398 				copydt._intatts[pm] = InternalRendAtts::intersectionSet(copydt._intatts[size_t(pm)], _meaningfulattsperprimitive[size_t(pm)]);
399 			_perviewreqatts[viewid] = copydt;
400 		}
401 
setPerAllViewsInfo(const PVData & data)402 		void setPerAllViewsInfo(const PVData& data)
403 		{
404 			///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
405 			PVData copydt(data);
406 			for (PRIMITIVE_MODALITY pm = PRIMITIVE_MODALITY(0); pm < PR_ARITY; pm = next(pm))
407 				copydt._intatts[pm] = InternalRendAtts::intersectionSet(copydt._intatts[size_t(pm)], _meaningfulattsperprimitive[size_t(pm)]);
408 			for (typename ViewsMap::iterator it = _perviewreqatts.begin(); it != _perviewreqatts.end(); ++it)
409 				it->second = copydt;
410 		}
411 
removeView(UNIQUE_VIEW_ID_TYPE viewid)412 		bool removeView(UNIQUE_VIEW_ID_TYPE viewid)
413 		{
414 			typename ViewsMap::iterator it = _perviewreqatts.find(viewid);
415 			if (it == _perviewreqatts.end())
416 				return false;
417 			_perviewreqatts.erase(viewid);
418 			return true;
419 		}
420 
removeAllViews()421 		void removeAllViews()
422 		{
423 			_perviewreqatts.clear();
424 		}
425 
426 		void draw(UNIQUE_VIEW_ID_TYPE viewid, const std::vector<GLuint>& textid = std::vector<GLuint>()) const
427 		{
428 			typename ViewsMap::const_iterator it = _perviewreqatts.find(viewid);
429 			if (it == _perviewreqatts.end())
430 				return;
431 
432 			const PVData& dt = it->second;
433 			//const InternalRendAtts& atts = it->second._intatts;
434 			drawFun(dt, textid);
435 		}
436 
437 
438 		void drawAllocatedAttributesSubset(UNIQUE_VIEW_ID_TYPE viewid, const PVData& dt, const std::vector<GLuint>& textid = std::vector<GLuint>()) const
439 		{
440 			typename ViewsMap::const_iterator it = _perviewreqatts.find(viewid);
441 			if (it == _perviewreqatts.end())
442 				return;
443 
444 			PVData tmp = dt;
445 
446 			if (!(_currallocatedboatt[INT_ATT_NAMES::ATT_VERTPOSITION]))
447 			{
448 				for (PRIMITIVE_MODALITY pm = PRIMITIVE_MODALITY(0); pm < PR_ARITY; pm = next(pm))
449 				{
450 					tmp._pmmask[size_t(pm)] = 0;
451 					tmp._intatts[size_t(pm)] = InternalRendAtts();
452 				}
453 			}
454 			else
455 			{
456 				for (PRIMITIVE_MODALITY pm = PRIMITIVE_MODALITY(0); pm < PR_ARITY; pm = next(pm))
457 				{
458 					tmp._intatts[size_t(pm)] = InternalRendAtts::intersectionSet(tmp._intatts[size_t(pm)], _meaningfulattsperprimitive[size_t(pm)]);
459 					tmp._intatts[size_t(pm)] = InternalRendAtts::intersectionSet(tmp._intatts[size_t(pm)], _currallocatedboatt);
460 				}
461 			}
462 			drawFun(dt, textid);
463 		}
464 
isBORenderingAvailable()465 		bool isBORenderingAvailable() const
466 		{
467 			return _borendering;
468 		}
469 
manageBuffers()470 		bool manageBuffers()
471 		{
472 			InternalRendAtts tobeallocated;
473 			InternalRendAtts tobedeallocated;
474 			InternalRendAtts tobeupdated;
475 			bool correctlyallocated = false;
476 			bool arebuffersok = checkBuffersAllocationStatus(tobeallocated, tobedeallocated, tobeupdated);
477 			if (!arebuffersok)
478 				correctlyallocated = manageAndFeedBuffersIfNeeded(tobeallocated, tobedeallocated, tobeupdated);
479 			if (_debugmode)
480 				debug(tobeallocated, tobedeallocated, tobeupdated);
481 			return (arebuffersok || correctlyallocated);
482 		}
483 
484 
setGLOptions(UNIQUE_VIEW_ID_TYPE viewid,const GL_OPTIONS_DERIVED_TYPE & opts)485 		void setGLOptions(UNIQUE_VIEW_ID_TYPE viewid, const GL_OPTIONS_DERIVED_TYPE& opts)
486 		{
487 			typename ViewsMap::iterator it = _perviewreqatts.find(viewid);
488 			if (it == _perviewreqatts.end())
489 				return;
490 			it->second.set(opts);
491 		}
492 
setTrMatrix(const vcg::Matrix44<typename MESH_TYPE::ScalarType> & tr)493 		void setTrMatrix(const vcg::Matrix44<typename MESH_TYPE::ScalarType>& tr)
494 		{
495 			_tr = tr;
496 		}
497 
setDebugMode(bool isdebug)498 		void setDebugMode(bool isdebug)
499 		{
500 			_debugmode = isdebug;
501 		}
502 
getLog(DebugInfo & info)503 		void getLog(DebugInfo& info)
504 		{
505 			info.reset();
506 			info._tobedeallocated = _loginfo._tobedeallocated;
507 			info._tobeallocated = _loginfo._tobeallocated;
508 			info._tobeupdated = _loginfo._tobeupdated;
509 
510 			info._currentlyallocated = _loginfo._currentlyallocated;
511 			info._perviewdata = _loginfo._perviewdata;
512 			_loginfo.reset();
513 		}
514 
515 	private:
initMeaningfulAttsMask()516 		void initMeaningfulAttsMask()
517 		{
518 			_meaningfulattsperprimitive[PR_POINTS][INT_ATT_NAMES::ATT_VERTPOSITION] = true;
519 			_meaningfulattsperprimitive[PR_POINTS][INT_ATT_NAMES::ATT_VERTNORMAL] = true;
520 			_meaningfulattsperprimitive[PR_POINTS][INT_ATT_NAMES::ATT_VERTCOLOR] = true;
521 			//_meaningfulattsperprimitive[PR_POINTS][INT_ATT_NAMES::ATT_FIXEDCOLOR] = true;
522 			_meaningfulattsperprimitive[PR_POINTS][INT_ATT_NAMES::ATT_VERTTEXTURE] = true;
523 
524 			_meaningfulattsperprimitive[PR_WIREFRAME_EDGES][INT_ATT_NAMES::ATT_VERTPOSITION] = true;
525 			_meaningfulattsperprimitive[PR_WIREFRAME_EDGES][INT_ATT_NAMES::ATT_VERTNORMAL] = true;
526 			_meaningfulattsperprimitive[PR_WIREFRAME_EDGES][INT_ATT_NAMES::ATT_VERTCOLOR] = true;
527 			//_meaningfulattsperprimitive[PR_WIREFRAME_EDGES][INT_ATT_NAMES::ATT_FIXEDCOLOR] = true;
528 			_meaningfulattsperprimitive[PR_WIREFRAME_EDGES][INT_ATT_NAMES::ATT_EDGEINDICES] = true;
529 
530 			_meaningfulattsperprimitive[PR_WIREFRAME_TRIANGLES][INT_ATT_NAMES::ATT_VERTPOSITION] = true;
531 			_meaningfulattsperprimitive[PR_WIREFRAME_TRIANGLES][INT_ATT_NAMES::ATT_VERTNORMAL] = true;
532 			_meaningfulattsperprimitive[PR_WIREFRAME_TRIANGLES][INT_ATT_NAMES::ATT_VERTCOLOR] = true;
533 			//_meaningfulattsperprimitive[PR_WIREFRAME_TRIANGLES][INT_ATT_NAMES::ATT_FIXEDCOLOR] = true;
534 			_meaningfulattsperprimitive[PR_WIREFRAME_TRIANGLES][INT_ATT_NAMES::ATT_VERTINDICES] = true;
535 
536 			_meaningfulattsperprimitive[PR_SOLID][INT_ATT_NAMES::ATT_VERTPOSITION] = true;
537 			_meaningfulattsperprimitive[PR_SOLID][INT_ATT_NAMES::ATT_VERTNORMAL] = true;
538 			_meaningfulattsperprimitive[PR_SOLID][INT_ATT_NAMES::ATT_FACENORMAL] = true;
539 			_meaningfulattsperprimitive[PR_SOLID][INT_ATT_NAMES::ATT_VERTCOLOR] = true;
540 			_meaningfulattsperprimitive[PR_SOLID][INT_ATT_NAMES::ATT_FACECOLOR] = true;
541 			//_meaningfulattsperprimitive[PR_SOLID][INT_ATT_NAMES::ATT_FIXEDCOLOR] = true;
542 			_meaningfulattsperprimitive[PR_SOLID][INT_ATT_NAMES::ATT_VERTTEXTURE] = true;
543 			_meaningfulattsperprimitive[PR_SOLID][INT_ATT_NAMES::ATT_WEDGETEXTURE] = true;
544 			_meaningfulattsperprimitive[PR_SOLID][INT_ATT_NAMES::ATT_VERTINDICES] = true;
545 		}
546 
hasMeshAttribute(INT_ATT_NAMES attname)547 		bool hasMeshAttribute(INT_ATT_NAMES attname) const
548 		{
549 			switch (attname)
550 			{
551 			case(INT_ATT_NAMES::ATT_VERTPOSITION):
552 				return true;
553 			case(INT_ATT_NAMES::ATT_VERTNORMAL):
554 				return vcg::tri::HasPerVertexNormal(_mesh);
555 			case(INT_ATT_NAMES::ATT_FACENORMAL):
556 				return vcg::tri::HasPerFaceNormal(_mesh);
557 			case(INT_ATT_NAMES::ATT_VERTCOLOR):
558 				return vcg::tri::HasPerVertexColor(_mesh);
559 			case(INT_ATT_NAMES::ATT_FACECOLOR):
560 				return vcg::tri::HasPerFaceColor(_mesh);
561 				/*case(INT_ATT_NAMES::ATT_FIXEDCOLOR):
562 					return true;*/
563 			case(INT_ATT_NAMES::ATT_VERTTEXTURE):
564 				return vcg::tri::HasPerVertexTexCoord(_mesh);
565 			case(INT_ATT_NAMES::ATT_WEDGETEXTURE):
566 				return vcg::tri::HasPerWedgeTexCoord(_mesh);
567 			case(INT_ATT_NAMES::ATT_VERTINDICES):
568 				return (_mesh.VN() != 0) && (_mesh.FN() != 0);
569 			case(INT_ATT_NAMES::ATT_EDGEINDICES):
570 				return vcg::tri::HasPerVertexFlags(_mesh) || ((_mesh.VN() != 0) && (_mesh.FN() == 0) && (_mesh.EN() == 0));
571 			default:
572 				return false;
573 			}
574 			return false;
575 		}
576 
checkBuffersAllocationStatus(InternalRendAtts & tobeallocated,InternalRendAtts & tobedeallocated,InternalRendAtts & tobeupdated)577 		bool checkBuffersAllocationStatus(InternalRendAtts& tobeallocated, InternalRendAtts& tobedeallocated, InternalRendAtts& tobeupdated) const
578 		{
579 			bool somethingtodo = false;
580 			tobedeallocated.reset();
581 			tobedeallocated.reset();
582 			tobeupdated.reset();
583 
584 			//bool thereisreplicatedview = isThereAReplicatedPipelineView();
585 			InternalRendAtts meaningfulrequiredbyatleastoneview;
586 			InternalRendAtts probabilyuseless;
587 
588 			for (typename ViewsMap::const_iterator it = _perviewreqatts.begin(); it != _perviewreqatts.end(); ++it)
589 			{
590 				for (PRIMITIVE_MODALITY pm = PRIMITIVE_MODALITY(0); pm < PR_ARITY; pm = next(pm))
591 				{
592 					//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
593 					//by some other rendered primitive
594 					//the vertindices is, as usual, a different case
595 					if (it->second._intatts[size_t(pm)][INT_ATT_NAMES::ATT_VERTPOSITION])
596 						meaningfulrequiredbyatleastoneview = InternalRendAtts::unionSet(meaningfulrequiredbyatleastoneview, it->second._intatts[size_t(pm)]);
597 					else
598 						probabilyuseless = InternalRendAtts::unionSet(probabilyuseless, it->second._intatts[size_t(pm)]);
599 				}
600 			}
601 			bool thereisreplicatedview = InternalRendAtts::replicatedPipelineNeeded(meaningfulrequiredbyatleastoneview);
602 			meaningfulrequiredbyatleastoneview[INT_ATT_NAMES::ATT_VERTINDICES] &= !thereisreplicatedview;
603 
604 			InternalRendAtts reallyuseless = InternalRendAtts::complementSet(probabilyuseless, meaningfulrequiredbyatleastoneview);
605 
606 			bool switchreplicatedindexed = (!InternalRendAtts::replicatedPipelineNeeded(_currallocatedboatt) && thereisreplicatedview) || (InternalRendAtts::replicatedPipelineNeeded(_currallocatedboatt) && !thereisreplicatedview);
607 
608 			/*in some way the vertices number changed. If i use the indexed pipeline i have to deallocate/allocate/update the vertex indices*/
609 			bool numvertchanged = boExpectedSize(INT_ATT_NAMES::ATT_VERTPOSITION, thereisreplicatedview) != _bo[INT_ATT_NAMES::ATT_VERTPOSITION]->_size;
610 			bool vertindforcedupdate = numvertchanged && meaningfulrequiredbyatleastoneview[INT_ATT_NAMES::ATT_VERTINDICES];
611 
612 			InternalRendAtts probablytoallocate = InternalRendAtts::complementSet(meaningfulrequiredbyatleastoneview, _currallocatedboatt);
613 			InternalRendAtts probablytodeallocate = InternalRendAtts::complementSet(_currallocatedboatt, meaningfulrequiredbyatleastoneview);
614 			for (unsigned int ii = 0; ii < INT_ATT_NAMES::enumArity(); ++ii)
615 			{
616 				INT_ATT_NAMES boname(ii);
617 				if (_bo[boname] != NULL)
618 				{
619 					bool hasmeshattribute = hasMeshAttribute(boname);
620 					bool isvalid = (_bo[boname]->_isvalid);
621 					bool notempty = (_bo[boname]->_size > 0);
622 					if (boname != INT_ATT_NAMES::ATT_EDGEINDICES)
623 					{
624 						size_t sz = boExpectedSize(boname, thereisreplicatedview);
625 
626 						tobedeallocated[boname] = (notempty && !hasmeshattribute) ||
627 							(notempty && probablytodeallocate[boname]) ||
628 							(notempty && reallyuseless[boname]) ||
629 							(notempty && (_bo[boname]->_size != sz) && meaningfulrequiredbyatleastoneview[boname]) ||
630 							(notempty && (boname == INT_ATT_NAMES::ATT_VERTINDICES) && (vertindforcedupdate));
631 						tobeallocated[boname] = (hasmeshattribute && (sz > 0) && (sz != _bo[boname]->_size) && meaningfulrequiredbyatleastoneview[boname]) ||
632 							(hasmeshattribute && (sz > 0) && probablytoallocate[boname]) ||
633 							(hasmeshattribute && (boname == INT_ATT_NAMES::ATT_VERTINDICES) && (vertindforcedupdate));
634 						tobeupdated[boname] = tobeallocated[boname] || (hasmeshattribute && (sz > 0) && !(isvalid) && meaningfulrequiredbyatleastoneview[boname]);
635 					}
636 					else
637 					{
638 						bool meshchanged = ((size_t(_mesh.FN()) != _meshtriangleswhenedgeindiceswerecomputed) || (size_t(_mesh.VN()) != _meshverticeswhenedgeindiceswerecomputed));
639 						tobedeallocated[INT_ATT_NAMES::ATT_EDGEINDICES] = (notempty && !hasmeshattribute) ||
640 							(notempty && !meaningfulrequiredbyatleastoneview[INT_ATT_NAMES::ATT_EDGEINDICES]) ||
641 							(notempty && !(isvalid) && meshchanged);
642 						tobeallocated[INT_ATT_NAMES::ATT_EDGEINDICES] = (hasmeshattribute && meaningfulrequiredbyatleastoneview[INT_ATT_NAMES::ATT_EDGEINDICES] && !(isvalid) && (meshchanged)) ||
643 							(hasmeshattribute && meaningfulrequiredbyatleastoneview[INT_ATT_NAMES::ATT_EDGEINDICES] && !(isvalid) && !(_currallocatedboatt[INT_ATT_NAMES::ATT_EDGEINDICES]));
644 						tobeupdated[INT_ATT_NAMES::ATT_EDGEINDICES] = tobeallocated[INT_ATT_NAMES::ATT_EDGEINDICES] ||
645 							(hasmeshattribute && !(isvalid) && meaningfulrequiredbyatleastoneview[INT_ATT_NAMES::ATT_EDGEINDICES]) ||
646 							(hasmeshattribute && switchreplicatedindexed && meaningfulrequiredbyatleastoneview[INT_ATT_NAMES::ATT_EDGEINDICES]);
647 					}
648 				}
649 				somethingtodo = somethingtodo || tobeallocated[boname] || tobedeallocated[boname] || tobeupdated[boname];
650 			}
651 			return !(somethingtodo);
652 		}
653 
manageAndFeedBuffersIfNeeded(const InternalRendAtts & tobeallocated,const InternalRendAtts & tobedeallocated,const InternalRendAtts & tobeupdated)654 		bool manageAndFeedBuffersIfNeeded(const InternalRendAtts& tobeallocated, const InternalRendAtts& tobedeallocated, const InternalRendAtts& tobeupdated)
655 		{
656 			if (tobeupdated[INT_ATT_NAMES::ATT_EDGEINDICES])
657 				updateEdgeVertIndVector();
658 
659 			bool immediatemode = !(buffersMemoryManagementFunction(tobeallocated, tobedeallocated, tobeupdated));
660 			bool replicated = isThereAReplicatedPipelineView();
661 
662 			if (immediatemode)
663 				return false;
664 
665 			bool somethingtoupdate = false;
666 			for (unsigned int hh = 0; hh < INT_ATT_NAMES::enumArity(); ++hh)
667 				somethingtoupdate = somethingtoupdate || tobeupdated[hh];
668 
669 			if (somethingtoupdate)
670 			{
671 				if (replicated)
672 				{
673 					InternalRendAtts attributestobeupdated(tobeupdated);
674 					//WARNING!In case we have to update the wedgetexture bo maybe (not always!) we must update also the other buffer already in memory
675 					//cause the wedgetexture pipeline force a change in the order of the triangles in GPU.
676 					//they are now ordered by the texture seam and not more by the triangle index!
677 					if (tobeupdated[INT_ATT_NAMES::ATT_WEDGETEXTURE])
678 						attributestobeupdated = _currallocatedboatt;
679 					updateBuffersReplicatedPipeline(attributestobeupdated);
680 				}
681 				else
682 					updateBuffersIndexedPipeline(tobeupdated);
683 				glFinish();
684 			}
685 			return true;
686 		}
687 
updateEdgeVertIndVector()688 		void updateEdgeVertIndVector()
689 		{
690 			_edge.clear();
691 			fillUniqueEdgeVector(_mesh, _edge);
692 			_meshverticeswhenedgeindiceswerecomputed = _mesh.VN();
693 			_meshtriangleswhenedgeindiceswerecomputed = _mesh.FN();
694 		}
695 
buffersMemoryManagementFunction(const InternalRendAtts & tobeallocated,const InternalRendAtts & tobedeallocated,const InternalRendAtts & tobeupdated)696 		bool buffersMemoryManagementFunction(const InternalRendAtts& tobeallocated, const InternalRendAtts& tobedeallocated, const InternalRendAtts& tobeupdated)
697 		{
698 			//GLenum err = glGetError();
699 			bool replicated = isThereAReplicatedPipelineView();
700 			std::ptrdiff_t newallocatedmem = bufferObjectsMemoryRequired(tobeallocated);
701 			std::ptrdiff_t deallocatedmem = bufferObjectsMemoryRequired(tobedeallocated);
702 			ptrdiff_t zero = 0;
703 			std::ptrdiff_t changedsize = std::max(zero, newallocatedmem - deallocatedmem);
704 			//std::ptrdiff_t bomemoryrequiredbymesh = bufferObjectsMemoryRequired(_currallocatedboatt) - deallocatedmem + newallocatedmem;
705 			unsigned int ii = 0;
706 			for (typename std::vector<GLBufferObject*>::iterator it = _bo.begin(); it != _bo.end(); ++it)
707 			{
708 				INT_ATT_NAMES boname(ii);
709 				//size_t sz = boExpectedSize(boname,replicated);
710 				//size_t dim = boExpectedDimension(boname,replicated);
711 
712 				if (tobedeallocated[boname])
713 					bufferDeAllocationRequested(boname);
714 				++ii;
715 			}
716 
717 			if (!_gpumeminfo.isAdditionalMemoryAvailable(changedsize))
718 			{
719 				std::cout << "no additional memory available!!! memory required: " << changedsize << std::endl;
720 				ii = 0;
721 				for (typename std::vector<GLBufferObject*>::iterator it = _bo.begin(); it != _bo.end(); ++it)
722 				{
723 					INT_ATT_NAMES boname(ii);
724 					size_t sz(boExpectedSize(boname, replicated));
725 					//there are already valid mesh attributes properly allocated in memory but there is not enough gpu memory for the remaining mesh.
726 					//we have to deallocate the previously allocated mesh attributes
727 					if ((*it != NULL) && ((sz == (*it)->_size)))
728 						bufferDeAllocationRequested(boname);
729 					++ii;
730 				}
731 				_borendering = false;
732 				return false;
733 			}
734 			else
735 			{
736 				bool failedallocation = false;
737 				unsigned int ii = 0;
738 				typename std::vector<GLBufferObject*>::iterator it = _bo.begin();
739 				while ((it != _bo.end()) && (!failedallocation))
740 				{
741 					INT_ATT_NAMES boname(ii);
742 					GLBufferObject* cbo = _bo[ii];
743 					if (tobeallocated[boname])
744 					{
745 						cbo->_size = boExpectedSize(boname, replicated);
746 						std::ptrdiff_t dim = boExpectedDimension(boname, replicated);
747 						glGenBuffers(1, &cbo->_bohandle);
748 						glBindBuffer(cbo->_target, cbo->_bohandle);
749 						//we call glGetError BEFORE the glBufferData function in order to clean the error flag
750 						GLenum err = glGetError();
751 						//assert(err == GL_NO_ERROR);
752 						glBufferData(cbo->_target, dim, NULL, GL_STATIC_DRAW);
753 						err = glGetError();
754 						//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
755 						failedallocation = (err == GL_OUT_OF_MEMORY) || (!_gpumeminfo.isAdditionalMemoryAvailable(dim));
756 						if (!failedallocation)
757 						{
758 							//setBufferPointerEnableClientState(boname);
759 							setBufferPointer(boname);
760 							_gpumeminfo.acquiredMemory(dim);
761 						}
762 						cbo->_isvalid = !failedallocation;
763 						_borendering = !failedallocation;
764 						glBindBuffer(cbo->_target, 0);
765 						_currallocatedboatt[boname] = !failedallocation;
766 					}
767 					else
768 					{
769 						//the arity of the attribute contained in the bo didn't change so i can use the old space without reallocating it
770 						if (cbo != NULL)
771 							cbo->_isvalid = cbo->_isvalid || tobeupdated[boname];
772 					}
773 					++it;
774 					++ii;
775 				}
776 				if (failedallocation)
777 					buffersDeAllocationRequested(_currallocatedboatt);
778 				_borendering = !failedallocation;
779 			}
780 			return _borendering;
781 		}
782 
updateBuffersIndexedPipeline(const InternalRendAtts & attributestobeupdated)783 		bool updateBuffersIndexedPipeline(const InternalRendAtts& attributestobeupdated)
784 		{
785 			_chunkmap.clear();
786 			size_t vn = _mesh.VN();
787 			size_t tn = _mesh.FN();
788 
789 			size_t facechunk = std::min(size_t(tn), _perbatchprim);
790 			size_t vertexchunk = std::min(size_t(vn), _perbatchprim);
791 
792 			std::vector<vcg::Point3f> pv; //position vector
793 			if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTPOSITION])
794 				pv.resize(vertexchunk);
795 
796 			std::vector<vcg::Point3f> nv; //per vertex normal vector
797 			if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTNORMAL])
798 				nv.resize(vertexchunk);
799 
800 			std::vector<vcg::Color4b> cv; // Per vertex color vector
801 			if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTCOLOR])
802 				cv.resize(vertexchunk);
803 
804 			std::vector<float> tv; // per vertex texture coord vector
805 			if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTTEXTURE])
806 				tv.resize(vertexchunk * 2);
807 
808 			size_t chunkingpu = 0;
809 
810 			for (size_t i = 0; i < vn; ++i)
811 			{
812 				size_t chunkindex = i % vertexchunk;
813 				if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTPOSITION])
814 					pv[chunkindex].Import(_mesh.vert[i].cP());
815 
816 				if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTNORMAL])
817 				{
818 					nv[chunkindex].Import(_mesh.vert[i].cN());
819 					nv[chunkindex].Normalize();
820 				}
821 
822 				if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTCOLOR])
823 				{
824 					cv[chunkindex] = _mesh.vert[i].cC();
825 				}
826 				if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTTEXTURE])
827 				{
828 					tv[chunkindex * 2 + 0] = _mesh.vert[i].cT().U();
829 					tv[chunkindex * 2 + 1] = _mesh.vert[i].cT().V();
830 				}
831 
832 				if ((i == vn - 1) || (chunkindex == vertexchunk - 1))
833 				{
834 					size_t chunksize = vertexchunk;
835 					if (i == vn - 1)
836 						chunksize = chunkindex + 1;
837 
838 					if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTPOSITION])
839 					{
840 						GLBufferObject* buffobj = _bo[INT_ATT_NAMES::ATT_VERTPOSITION];
841 						glBindBuffer(GL_ARRAY_BUFFER, buffobj->_bohandle);
842 						glBufferSubData(GL_ARRAY_BUFFER, chunkingpu * vertexchunk * buffobj->_components * buffobj->getSizeOfGLType(), buffobj->_components * buffobj->getSizeOfGLType() * chunksize, &pv[0]);
843 						//std::vector<vcg::Point3f> tmppv; //position vector
844 						//if (attributestobeupdated[GLMeshAttributesInfo::ATT_VERTPOSITION])
845 						//    tmppv.resize(vertexchunk);
846 						//glGetBufferSubData(GL_ARRAY_BUFFER,0,buffobj->_components * buffobj->getSizeOfGLType() * chunksize,&tmppv[0]);
847 						glBindBuffer(GL_ARRAY_BUFFER, 0);
848 
849 					}
850 					if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTNORMAL])
851 					{
852 						GLBufferObject* buffobj = _bo[INT_ATT_NAMES::ATT_VERTNORMAL];
853 						glBindBuffer(GL_ARRAY_BUFFER, buffobj->_bohandle);
854 						glBufferSubData(GL_ARRAY_BUFFER, chunkingpu * vertexchunk * buffobj->_components * buffobj->getSizeOfGLType(), buffobj->_components * buffobj->getSizeOfGLType() * chunksize, &nv[0]);
855 						glBindBuffer(GL_ARRAY_BUFFER, 0);
856 					}
857 					if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTCOLOR])
858 					{
859 						GLBufferObject* buffobj = _bo[INT_ATT_NAMES::ATT_VERTCOLOR];
860 						glBindBuffer(GL_ARRAY_BUFFER, buffobj->_bohandle);
861 						glBufferSubData(GL_ARRAY_BUFFER, chunkingpu * vertexchunk * buffobj->_components * buffobj->getSizeOfGLType(), buffobj->_components * buffobj->getSizeOfGLType() * chunksize, &cv[0]);
862 						glBindBuffer(GL_ARRAY_BUFFER, 0);
863 					}
864 					if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTTEXTURE])
865 					{
866 						GLBufferObject* buffobj = _bo[INT_ATT_NAMES::ATT_VERTTEXTURE];
867 						glBindBuffer(GL_ARRAY_BUFFER, buffobj->_bohandle);
868 						glBufferSubData(GL_ARRAY_BUFFER, chunkingpu * vertexchunk * buffobj->_components * buffobj->getSizeOfGLType(), buffobj->_components * buffobj->getSizeOfGLType() * chunksize, &tv[0]);
869 						glBindBuffer(GL_ARRAY_BUFFER, 0);
870 					}
871 					glFinish();
872 					++chunkingpu;
873 				}
874 			}
875 
876 			pv.clear();
877 			nv.clear();
878 			cv.clear();
879 			tv.clear();
880 
881 			chunkingpu = 0;
882 			std::vector<GLuint> ti(facechunk * 3);
883 			for (size_t i = 0; i < tn; ++i)
884 			{
885 				size_t chunkindex = i % facechunk;
886 
887 				ti[chunkindex * 3 + 0] = GLuint(vcg::tri::Index(_mesh, _mesh.face[i].V(0)));
888 				ti[chunkindex * 3 + 1] = GLuint(vcg::tri::Index(_mesh, _mesh.face[i].V(1)));
889 				ti[chunkindex * 3 + 2] = GLuint(vcg::tri::Index(_mesh, _mesh.face[i].V(2)));
890 
891 				if ((i == tn - 1) || (chunkindex == facechunk - 1))
892 				{
893 					size_t chunksize = facechunk;
894 					if (i == tn - 1)
895 						chunksize = chunkindex + 1;
896 
897 					if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTINDICES])
898 					{
899 						glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _bo[INT_ATT_NAMES::ATT_VERTINDICES]->_bohandle);
900 						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]);
901 						glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
902 					}
903 					++chunkingpu;
904 				}
905 			}
906 			if ((attributestobeupdated[INT_ATT_NAMES::ATT_EDGEINDICES]) && (_edge.size() > 0))
907 			{
908 				glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _bo[INT_ATT_NAMES::ATT_EDGEINDICES]->_bohandle);
909 				glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, _bo[INT_ATT_NAMES::ATT_EDGEINDICES]->_components *  _edge.size() * _bo[INT_ATT_NAMES::ATT_EDGEINDICES]->getSizeOfGLType(), &_edge[0]);
910 				glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
911 			}
912 			return true;
913 		}
914 
isThereAReplicatedPipelineView()915 		bool isThereAReplicatedPipelineView() const
916 		{
917 			bool replicated = false;
918 			for (typename ViewsMap::const_iterator it = _perviewreqatts.begin(); it != _perviewreqatts.end(); ++it)
919 			{
920 				//There is a replicated pipeline only if the att[ATT_VERTPOSITION] is true, otherwise is a spurious replicated view
921 				for (size_t pm = 0; pm < size_t(PR_ARITY); ++pm)
922 					replicated = replicated || (InternalRendAtts::replicatedPipelineNeeded(it->second._intatts[pm]) && (it->second._pmmask.test(pm)));
923 			}
924 			return replicated;
925 		}
926 
isThereAnEdgesView()927 		bool isThereAnEdgesView() const
928 		{
929 			bool isthereaquadview = false;
930 			for (typename ViewsMap::const_iterator it = _perviewreqatts.begin(); it != _perviewreqatts.end(); ++it)
931 				isthereaquadview = (it->second._intatts[size_t(PR_WIREFRAME_EDGES)][INT_ATT_NAMES::ATT_VERTPOSITION]) || isthereaquadview;
932 			return isthereaquadview;
933 		}
934 
935 
updateBuffersReplicatedPipeline(const InternalRendAtts & attributestobeupdated)936 		bool updateBuffersReplicatedPipeline(const InternalRendAtts& attributestobeupdated)
937 		{
938 			size_t tn = _mesh.fn;
939 
940 			size_t facechunk = std::min(size_t(tn), _perbatchprim);
941 
942 			std::vector<vcg::Point3f> rpv; //position vector
943 			if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTPOSITION])
944 				rpv.resize(facechunk * 3);
945 
946 			std::vector<vcg::Point3f> rnv; //per vertex normal vector
947 			if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTNORMAL])
948 				rnv.resize(facechunk * 3);
949 
950 			std::vector<vcg::Point3f> rfnv; //per face normal vector
951 			if (attributestobeupdated[INT_ATT_NAMES::ATT_FACENORMAL])
952 				rfnv.resize(facechunk * 3);
953 
954 			std::vector<vcg::Color4b> rcv; // Per vertex color vector
955 			if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTCOLOR])
956 				rcv.resize(facechunk * 3);
957 
958 			std::vector<vcg::Color4b> rfcv; // Per vertex color vector
959 			if (attributestobeupdated[INT_ATT_NAMES::ATT_FACECOLOR])
960 				rfcv.resize(facechunk * 3);
961 
962 			std::vector<float> rtv; // per vertex texture coord vector
963 			if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTTEXTURE])
964 				rtv.resize(facechunk * 3 * 2);
965 
966 			std::vector<float> rwtv; // per wedge texture coord vector
967 			if (attributestobeupdated[INT_ATT_NAMES::ATT_WEDGETEXTURE])
968 				rwtv.resize(facechunk * 3 * 2);
969 
970 			size_t chunkingpu = 0;
971 
972 			//it's a map containing for each texture seams n a vector of all the triangle index ranges having n has texture seam
973 			//Suppose that in a mesh we have
974 			//TXS_0{t0,t1,t2,t3}, TXS_4{t4,t5},TXS_0{t6},TXS_-1{t7,t8,t9},TXS_4{t10,t11}
975 			//so chunkMap will contain
976 			// -1 -> [<t7,t9>]
977 			//  0 -> [<t0,t3>,<t6,t6>]
978 			//  4 -> [<t4,t5>,<t10,t11>]
979 			//
980 			//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
981 
982 
983 			if (attributestobeupdated[INT_ATT_NAMES::ATT_WEDGETEXTURE] || attributestobeupdated[INT_ATT_NAMES::ATT_VERTTEXTURE])
984 			{
985 				_chunkmap.clear();
986 				if (attributestobeupdated[INT_ATT_NAMES::ATT_WEDGETEXTURE])
987 					fillchunkMap();
988 				else
989 					if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTTEXTURE])
990 						_chunkmap[0].push_back(std::make_pair(0, tn - 1));
991 			}
992 
993 			//default case: no texture is required to be rendered but a non texture attribute has to be updated
994 			//we have to init the _chunkmap with just one entry (-1...that means no texture) referring all the triangles in the mesh
995 			if ((!_currallocatedboatt[INT_ATT_NAMES::ATT_VERTTEXTURE] && !_currallocatedboatt[INT_ATT_NAMES::ATT_WEDGETEXTURE]) &&
996 				(attributestobeupdated[INT_ATT_NAMES::ATT_VERTPOSITION] ||
997 					attributestobeupdated[INT_ATT_NAMES::ATT_VERTNORMAL] || attributestobeupdated[INT_ATT_NAMES::ATT_FACENORMAL] ||
998 					attributestobeupdated[INT_ATT_NAMES::ATT_VERTCOLOR] || attributestobeupdated[INT_ATT_NAMES::ATT_FACECOLOR]))
999 			{
1000 				_chunkmap.clear();
1001 				_chunkmap[-1].push_back(std::make_pair(0, tn - 1));
1002 			}
1003 
1004 			int t = 0;
1005 			if (attributestobeupdated[INT_ATT_NAMES::ATT_WEDGETEXTURE] || attributestobeupdated[INT_ATT_NAMES::ATT_VERTTEXTURE])
1006 			{
1007 				_texindnumtriangles.clear();
1008 				_texindnumtriangles.resize(_chunkmap.size());
1009 			}
1010 
1011 			std::vector<GLuint> vpatlas;
1012 			if (attributestobeupdated[INT_ATT_NAMES::ATT_EDGEINDICES])
1013 				vpatlas.resize(_mesh.VN(), UINT_MAX);
1014 
1015 			int faceind = 0;
1016 			size_t chunkindex = faceind;
1017 			GLuint triangles = 0;
1018 
1019 
1020 			for (ChunkMap::const_iterator mit = _chunkmap.begin(); mit != _chunkmap.end(); ++mit)
1021 			{
1022 				for (ChunkVector::const_iterator cit = mit->second.begin(); cit != mit->second.end(); ++cit)
1023 				{
1024 					for (size_t indf = cit->first; indf <= cit->second; ++indf)
1025 					{
1026 						chunkindex = faceind % facechunk;
1027 						if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTPOSITION])
1028 						{
1029 							rpv[chunkindex * 3 + 0].Import(_mesh.face[indf].V(0)->P());
1030 							rpv[chunkindex * 3 + 1].Import(_mesh.face[indf].V(1)->P());
1031 							rpv[chunkindex * 3 + 2].Import(_mesh.face[indf].V(2)->P());
1032 						}
1033 						if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTNORMAL])
1034 						{
1035 							rnv[chunkindex * 3 + 0].Import(_mesh.face[indf].V(0)->N().Normalize());
1036 							rnv[chunkindex * 3 + 1].Import(_mesh.face[indf].V(1)->N().Normalize());
1037 							rnv[chunkindex * 3 + 2].Import(_mesh.face[indf].V(2)->N().Normalize());
1038 						}
1039 
1040 						if (attributestobeupdated[INT_ATT_NAMES::ATT_FACENORMAL])
1041 						{
1042 							rfnv[chunkindex * 3 + 0].Import(_mesh.face[indf].N().Normalize());
1043 							rfnv[chunkindex * 3 + 1].Import(_mesh.face[indf].N().Normalize());
1044 							rfnv[chunkindex * 3 + 2].Import(_mesh.face[indf].N().Normalize());
1045 						}
1046 
1047 						if ((attributestobeupdated[INT_ATT_NAMES::ATT_VERTCOLOR]))
1048 						{
1049 							rcv[chunkindex * 3 + 0] = _mesh.face[indf].V(0)->C();
1050 							rcv[chunkindex * 3 + 1] = _mesh.face[indf].V(1)->C();
1051 							rcv[chunkindex * 3 + 2] = _mesh.face[indf].V(2)->C();
1052 						}
1053 
1054 						if ((attributestobeupdated[INT_ATT_NAMES::ATT_FACECOLOR]))
1055 						{
1056 							rfcv[chunkindex * 3 + 0] = _mesh.face[indf].C();
1057 							rfcv[chunkindex * 3 + 1] = _mesh.face[indf].C();
1058 							rfcv[chunkindex * 3 + 2] = _mesh.face[indf].C();
1059 						}
1060 
1061 						if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTTEXTURE])
1062 						{
1063 							rtv[chunkindex * 6 + 0] = float(_mesh.face[indf].V(0)->T().U());
1064 							rtv[chunkindex * 6 + 1] = float(_mesh.face[indf].V(0)->T().V());
1065 							rtv[chunkindex * 6 + 2] = float(_mesh.face[indf].V(1)->T().U());
1066 							rtv[chunkindex * 6 + 3] = float(_mesh.face[indf].V(1)->T().V());
1067 							rtv[chunkindex * 6 + 4] = float(_mesh.face[indf].V(2)->T().U());
1068 							rtv[chunkindex * 6 + 5] = float(_mesh.face[indf].V(2)->T().V());
1069 						}
1070 
1071 						if (attributestobeupdated[INT_ATT_NAMES::ATT_WEDGETEXTURE])
1072 						{
1073 							rwtv[chunkindex * 6 + 0] = float(_mesh.face[indf].WT(0).U());
1074 							rwtv[chunkindex * 6 + 1] = float(_mesh.face[indf].WT(0).V());
1075 							rwtv[chunkindex * 6 + 2] = float(_mesh.face[indf].WT(1).U());
1076 							rwtv[chunkindex * 6 + 3] = float(_mesh.face[indf].WT(1).V());
1077 							rwtv[chunkindex * 6 + 4] = float(_mesh.face[indf].WT(2).U());
1078 							rwtv[chunkindex * 6 + 5] = float(_mesh.face[indf].WT(2).V());
1079 						}
1080 
1081 						if (attributestobeupdated[INT_ATT_NAMES::ATT_EDGEINDICES])
1082 						{
1083 							for (int ii = 0; ii < 3; ++ii)
1084 							{
1085 								size_t v = vcg::tri::Index(_mesh, _mesh.face[indf].V(ii));
1086 								if (vpatlas[v] == UINT_MAX)
1087 									vpatlas[v] = faceind * 3 + ii;
1088 							}
1089 						}
1090 
1091 
1092 						if ((faceind == int(tn - 1)) || (chunkindex == size_t(facechunk - 1) ))
1093 						{
1094 							size_t chunksize = facechunk;
1095 							if (faceind == int(tn - 1))
1096 								chunksize = chunkindex + 1;
1097 
1098 							if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTPOSITION])
1099 							{
1100 								GLBufferObject* buffobj = _bo[INT_ATT_NAMES::ATT_VERTPOSITION];
1101 								glBindBuffer(GL_ARRAY_BUFFER, buffobj->_bohandle);
1102 								glBufferSubData(GL_ARRAY_BUFFER, chunkingpu * facechunk * 3 * buffobj->_components * buffobj->getSizeOfGLType(), 3 * buffobj->_components * buffobj->getSizeOfGLType() * chunksize, &rpv[0]);
1103 								glBindBuffer(GL_ARRAY_BUFFER, 0);
1104 							}
1105 
1106 							if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTNORMAL])
1107 							{
1108 								GLBufferObject* buffobj = _bo[INT_ATT_NAMES::ATT_VERTNORMAL];
1109 								glBindBuffer(GL_ARRAY_BUFFER, buffobj->_bohandle);
1110 								glBufferSubData(GL_ARRAY_BUFFER, chunkingpu * facechunk * 3 * buffobj->_components * buffobj->getSizeOfGLType(), 3 * buffobj->_components * buffobj->getSizeOfGLType() * chunksize, &rnv[0]);
1111 								glBindBuffer(GL_ARRAY_BUFFER, 0);
1112 							}
1113 
1114 							if (attributestobeupdated[INT_ATT_NAMES::ATT_FACENORMAL])
1115 							{
1116 								GLBufferObject* buffobj = _bo[INT_ATT_NAMES::ATT_FACENORMAL];
1117 								glBindBuffer(GL_ARRAY_BUFFER, buffobj->_bohandle);
1118 								glBufferSubData(GL_ARRAY_BUFFER, chunkingpu * facechunk * 3 * buffobj->_components * buffobj->getSizeOfGLType(), 3 * buffobj->_components * buffobj->getSizeOfGLType() * chunksize, &rfnv[0]);
1119 								glBindBuffer(GL_ARRAY_BUFFER, 0);
1120 							}
1121 
1122 							if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTCOLOR])
1123 							{
1124 								GLBufferObject* buffobj = _bo[INT_ATT_NAMES::ATT_VERTCOLOR];
1125 								glBindBuffer(GL_ARRAY_BUFFER, buffobj->_bohandle);
1126 								glBufferSubData(GL_ARRAY_BUFFER, chunkingpu * facechunk * 3 * buffobj->_components * buffobj->getSizeOfGLType(), 3 * buffobj->_components * buffobj->getSizeOfGLType() * chunksize, &rcv[0]);
1127 								glBindBuffer(GL_ARRAY_BUFFER, 0);
1128 							}
1129 
1130 							if (attributestobeupdated[INT_ATT_NAMES::ATT_FACECOLOR])
1131 							{
1132 								GLBufferObject* buffobj = _bo[INT_ATT_NAMES::ATT_FACECOLOR];
1133 								glBindBuffer(GL_ARRAY_BUFFER, buffobj->_bohandle);
1134 								glBufferSubData(GL_ARRAY_BUFFER, chunkingpu * facechunk * 3 * buffobj->_components * buffobj->getSizeOfGLType(), 3 * buffobj->_components * buffobj->getSizeOfGLType() * chunksize, &rfcv[0]);
1135 								glBindBuffer(GL_ARRAY_BUFFER, 0);
1136 							}
1137 
1138 							if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTTEXTURE])
1139 							{
1140 								GLBufferObject* buffobj = _bo[INT_ATT_NAMES::ATT_VERTTEXTURE];
1141 								glBindBuffer(GL_ARRAY_BUFFER, buffobj->_bohandle);
1142 								glBufferSubData(GL_ARRAY_BUFFER, chunkingpu * facechunk * 3 * buffobj->_components * buffobj->getSizeOfGLType(), 3 * buffobj->_components * buffobj->getSizeOfGLType() * chunksize, &rtv[0]);
1143 								glBindBuffer(GL_ARRAY_BUFFER, 0);
1144 							}
1145 
1146 							if (attributestobeupdated[INT_ATT_NAMES::ATT_WEDGETEXTURE])
1147 							{
1148 								GLBufferObject* buffobj = _bo[INT_ATT_NAMES::ATT_WEDGETEXTURE];
1149 								glBindBuffer(GL_ARRAY_BUFFER, buffobj->_bohandle);
1150 								glBufferSubData(GL_ARRAY_BUFFER, chunkingpu * facechunk * 3 * buffobj->_components * buffobj->getSizeOfGLType(), 3 * buffobj->_components * buffobj->getSizeOfGLType() * chunksize, &rwtv[0]);
1151 								glBindBuffer(GL_ARRAY_BUFFER, 0);
1152 							}
1153 
1154 							++chunkingpu;
1155 						}
1156 						++faceind;
1157 					}
1158 					triangles += cit->second - cit->first + 1;
1159 				}
1160 
1161 				if ((attributestobeupdated[INT_ATT_NAMES::ATT_EDGEINDICES]) && (_edge.size() > 0))
1162 				{
1163 					for (typename std::vector<EdgeVertInd>::iterator it = _edge.begin(); it != _edge.end(); ++it)
1164 					{
1165 						it->_v[0] = vpatlas[it->_v[0]];
1166 						it->_v[1] = vpatlas[it->_v[1]];
1167 					}
1168 
1169 					GLBufferObject* buffobj = _bo[INT_ATT_NAMES::ATT_EDGEINDICES];
1170 					glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffobj->_bohandle);
1171 					glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, buffobj->_components * buffobj->getSizeOfGLType() * _edge.size(), &_edge[0]);
1172 					glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1173 				}
1174 
1175 				if (attributestobeupdated[INT_ATT_NAMES::ATT_WEDGETEXTURE] || attributestobeupdated[INT_ATT_NAMES::ATT_VERTTEXTURE])
1176 					_texindnumtriangles[t] = std::make_pair(mit->first, triangles);
1177 				++t;
1178 			}
1179 
1180 			//return (k != tn)
1181 			//    throw MeshLabException("Mesh has not been properly partitioned");
1182 			return true;
1183 		}
1184 
buffersDeAllocationRequested(const InternalRendAtts & rq)1185 		void buffersDeAllocationRequested(const InternalRendAtts& rq)
1186 		{
1187 			for (unsigned int ii = 0; ii < INT_ATT_NAMES::enumArity(); ++ii)
1188 			{
1189 				INT_ATT_NAMES boname(ii);
1190 				if ((_bo[ii] != NULL) && (rq[boname]))
1191 					bufferDeAllocationRequested(boname);
1192 			}
1193 		}
1194 
bufferDeAllocationRequested(INT_ATT_NAMES att)1195 		void bufferDeAllocationRequested(INT_ATT_NAMES att)
1196 		{
1197 			unsigned int ind(att);
1198 			if ((ind < 0) || (ind >= (unsigned int)_bo.size()))
1199 				return;
1200 			GLBufferObject* bobj = _bo[ind];
1201 			if (bobj == NULL)
1202 				return;
1203 
1204 			if ((att != INT_ATT_NAMES::ATT_VERTINDICES) && (att != INT_ATT_NAMES::ATT_EDGEINDICES) /*&& (att != INT_ATT_NAMES::ATT_FIXEDCOLOR)*/)
1205 			{
1206 				glDisableClientState(bobj->_clientstatetag);
1207 			}
1208 			//glBufferData(bobj->_target, sizeof(vcg::Point3f)*_primitivebatch, 0, GL_DYNAMIC_DRAW);
1209 			glDeleteBuffers(1, &(bobj->_bohandle));
1210 			glFlush();
1211 			glFinish();
1212 
1213 			if (bobj->_size > 0)
1214 				//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
1215 				_gpumeminfo.releasedMemory(bobj->_size * bobj->getSizeOfGLType());
1216 			bobj->_isvalid = false;
1217 			bobj->_size = 0;
1218 			_currallocatedboatt[att] = false;
1219 		}
1220 
bufferObjectsMemoryRequired(const InternalRendAtts & rqatt)1221 		std::ptrdiff_t bufferObjectsMemoryRequired(const InternalRendAtts& rqatt) const
1222 		{
1223 			bool replicated = InternalRendAtts::replicatedPipelineNeeded(rqatt);
1224 			std::ptrdiff_t result(0);
1225 
1226 			for (unsigned int ii = 0; ii < INT_ATT_NAMES::enumArity(); ++ii)
1227 			{
1228 				INT_ATT_NAMES nm(ii);
1229 				if (rqatt[nm])
1230 					result += (std::ptrdiff_t) boExpectedDimension(nm, replicated);
1231 			}
1232 			return result;
1233 		}
1234 
1235 		//expected number of cells should have the required bo
1236 		//generateindex is true when i have a triangle based mesh
1237 		//				is false when i have a point based mesh
boExpectedSize(INT_ATT_NAMES name,bool replicatedpipeline)1238 		size_t boExpectedSize(INT_ATT_NAMES name, bool replicatedpipeline) const
1239 		{
1240 			try
1241 			{
1242 
1243 				GLBufferObject& cbo = *_bo.at((unsigned int)name);
1244 				size_t vertnum(_mesh.VN());
1245 				size_t facenum(_mesh.FN());
1246 
1247 				switch ((unsigned int)name)
1248 				{
1249 				case(INT_ATT_NAMES::ATT_VERTPOSITION):
1250 				case(INT_ATT_NAMES::ATT_VERTNORMAL):
1251 				case(INT_ATT_NAMES::ATT_VERTCOLOR):
1252 				case(INT_ATT_NAMES::ATT_VERTTEXTURE):
1253 				{
1254 					if (replicatedpipeline)
1255 						return facenum * 3 * cbo._components;
1256 					else
1257 						return vertnum * cbo._components;
1258 				}
1259 
1260 				case(INT_ATT_NAMES::ATT_FACENORMAL):
1261 				case(INT_ATT_NAMES::ATT_FACECOLOR):
1262 				case(INT_ATT_NAMES::ATT_WEDGETEXTURE):
1263 				{
1264 					if (replicatedpipeline)
1265 						return facenum * 3 * cbo._components;
1266 					else
1267 						return 0;
1268 				}
1269 				case(INT_ATT_NAMES::ATT_VERTINDICES):
1270 				{
1271 					if (replicatedpipeline)
1272 						return 0;
1273 					else
1274 						return facenum * cbo._components;
1275 				}
1276 				case(INT_ATT_NAMES::ATT_EDGEINDICES):
1277 				{
1278 					return _edge.size() * cbo._components;
1279 				}
1280 
1281 				default: break;
1282 				}
1283 			}
1284 			catch (std::out_of_range& /*exc*/)
1285 			{
1286 				return 0;
1287 			}
1288 			return 0;
1289 		}
1290 
boExpectedDimension(INT_ATT_NAMES name,bool replicatedpipeline)1291 		size_t boExpectedDimension(INT_ATT_NAMES name, bool replicatedpipeline) const
1292 		{
1293 			try
1294 			{
1295 				size_t sz = boExpectedSize(name, replicatedpipeline);
1296 				unsigned int ind = (unsigned int)name;
1297 				GLBufferObject* cbo = _bo.at(ind);
1298 				if (cbo == NULL)
1299 					return 0;
1300 				else
1301 					return sz * cbo->getSizeOfGLType();
1302 			}
1303 			catch (std::out_of_range& /*exc*/)
1304 			{
1305 				return 0;
1306 			}
1307 			return 0;
1308 		}
1309 
1310 		void drawFun(const PVData& dt, const std::vector<GLuint>& textid = std::vector<GLuint>()) const
1311 		{
1312 			glPushAttrib(GL_ALL_ATTRIB_BITS);
1313 			glMatrixMode(GL_MODELVIEW);
1314 			glPushMatrix();
1315 			glMultMatrix(_tr);
1316 
1317 			if ((dt._glopts != NULL) && (dt._glopts->_perbbox_enabled))
1318 				drawBBox(dt._glopts);
1319 
1320 			if (dt.isPrimitiveActive(PR_SOLID))
1321 			{
1322 				bool somethingmore = dt.isPrimitiveActive(PR_WIREFRAME_EDGES) || dt.isPrimitiveActive(PR_WIREFRAME_TRIANGLES) || dt.isPrimitiveActive(PR_POINTS);
1323 				if (somethingmore)
1324 				{
1325 					glEnable(GL_POLYGON_OFFSET_FILL);
1326 					glPolygonOffset(1.0, 1);
1327 				}
1328 				drawFilledTriangles(dt._intatts[size_t(PR_SOLID)], dt._glopts, textid);
1329 				if (somethingmore)
1330 					glDisable(GL_POLYGON_OFFSET_FILL);
1331 			}
1332 
1333 			if (dt.isPrimitiveActive(PR_WIREFRAME_EDGES) || dt.isPrimitiveActive(PR_WIREFRAME_TRIANGLES))
1334 			{
1335 				//InternalRendAtts tmpatts = atts;
1336 				bool pointstoo = dt.isPrimitiveActive(PR_POINTS);
1337 
1338 				if (pointstoo)
1339 				{
1340 					glEnable(GL_POLYGON_OFFSET_FILL);
1341 					glPolygonOffset(1.0, 1);
1342 				}
1343 				bool solidtoo = dt.isPrimitiveActive(PR_SOLID);
1344 
1345 				/*EDGE    |     TRI     |    DRAW
1346 				---------------------------------
1347 				  TRUE         TRUE         EDGE
1348 				  TRUE         FALSE        EDGE
1349 				  FALSE        TRUE         TRI
1350 				  FALSE        FALSE        NOTHING */
1351 
1352 				if (dt.isPrimitiveActive(PR_WIREFRAME_EDGES))
1353 					drawEdges(dt._intatts[size_t(PR_WIREFRAME_EDGES)], dt._glopts);
1354 				else
1355 				{
1356 					if (dt.isPrimitiveActive(PR_WIREFRAME_TRIANGLES))
1357 					{
1358 						drawWiredTriangles(dt._intatts[size_t(PR_WIREFRAME_TRIANGLES)], dt._glopts, textid);
1359 					}
1360 				}
1361 
1362 				if (pointstoo || solidtoo)
1363 					glDisable(GL_POLYGON_OFFSET_FILL);
1364 			}
1365 			if (dt.isPrimitiveActive(PR_POINTS))
1366 				drawPoints(dt._intatts[size_t(PR_POINTS)], dt._glopts, textid);
1367 
1368 			glPopMatrix();
1369 			glPopAttrib();
1370 			glFlush();
1371 			glFinish();
1372 		}
1373 
1374 		void drawFilledTriangles(const InternalRendAtts& req, const GL_OPTIONS_DERIVED_TYPE* glopts, const std::vector<GLuint>& textureindex = std::vector<GLuint>()) const
1375 		{
1376 			if (_mesh.VN() == 0)
1377 				return;
1378 
1379 			glPushAttrib(GL_ALL_ATTRIB_BITS);
1380 
1381 			bool isgloptsvalid = (glopts != NULL);
1382 
1383 			if (isgloptsvalid && glopts->_persolid_noshading)
1384 				glDisable(GL_LIGHTING);
1385 			else
1386 				if ((!isgloptsvalid) || (req[INT_ATT_NAMES::ATT_VERTNORMAL]) || (req[INT_ATT_NAMES::ATT_FACENORMAL]))
1387 				{
1388 					glEnable(GL_LIGHTING);
1389 				}
1390 
1391 			glEnable(GL_COLOR_MATERIAL);
1392 			if ((isgloptsvalid) && (glopts->_persolid_fixed_color_enabled))
1393 				glColor(glopts->_persolid_fixed_color);
1394 			else
1395 			{
1396 				if ((isgloptsvalid) && (glopts->_persolid_mesh_color_enabled))
1397 					glColor(_mesh.C());
1398 				else
1399 				{
1400 					if ((req[INT_ATT_NAMES::ATT_VERTCOLOR]) || (req[INT_ATT_NAMES::ATT_FACECOLOR]))
1401 						glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
1402 					else
1403 						glColor(vcg::Color4b(vcg::Color4b::LightGray));
1404 				}
1405 			}
1406 
1407 			if (isBORenderingAvailable())
1408 				drawTrianglesBO(req, textureindex);
1409 			else
1410 				drawTrianglesIM(req, textureindex);
1411 
1412 			glPopAttrib();
1413 		}
1414 
1415 
1416 		void drawWiredTriangles(const InternalRendAtts& req, const GL_OPTIONS_DERIVED_TYPE* glopts, const std::vector<GLuint>& textureindex = std::vector<GLuint>()) const
1417 		{
1418 			if (_mesh.VN() == 0)
1419 				return;
1420 			glPushAttrib(GL_ALL_ATTRIB_BITS);
1421 
1422 
1423 			bool isgloptsvalid = (glopts != NULL);
1424 
1425 			if (isgloptsvalid && glopts->_perwire_noshading)
1426 				glDisable(GL_LIGHTING);
1427 			else
1428 				if ((!isgloptsvalid) || (req[INT_ATT_NAMES::ATT_VERTNORMAL]))
1429 				{
1430 					glEnable(GL_LIGHTING);
1431 				}
1432 
1433 			glEnable(GL_COLOR_MATERIAL);
1434 			if ((isgloptsvalid) && (glopts->_perwire_fixed_color_enabled))
1435 				glColor(glopts->_perwire_fixed_color);
1436 			else
1437 			{
1438 				if ((isgloptsvalid) && (glopts->_perwire_mesh_color_enabled))
1439 					glColor(_mesh.C());
1440 				else
1441 				{
1442 					if (req[INT_ATT_NAMES::ATT_VERTCOLOR])
1443 						glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
1444 					else
1445 						glColor(vcg::Color4b(vcg::Color4b::DarkGray));
1446 				}
1447 			}
1448 			float linewidth = 1.0f;
1449 			if (isgloptsvalid)
1450 				linewidth = glopts->_perwire_wirewidth;
1451 			glLineWidth(linewidth);
1452 			glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
1453 
1454 			if (isBORenderingAvailable())
1455 				drawTrianglesBO(req, textureindex);
1456 			else
1457 				drawTrianglesIM(req, textureindex);
1458 
1459 			glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1460 			glPopAttrib();
1461 		}
1462 
1463 		void drawTrianglesBO(const InternalRendAtts& req, const std::vector<GLuint>& textureindex = std::vector<GLuint>()) const
1464 		{
1465 			updateClientState(req);
1466 
1467 			bool replicated = InternalRendAtts::replicatedPipelineNeeded(_currallocatedboatt);
1468 
1469 			if (replicated)
1470 			{
1471 				//qDebug("Replicated drawing");
1472 				int firsttriangleoffset = 0;
1473 				if (!req[INT_ATT_NAMES::ATT_VERTTEXTURE] && !req[INT_ATT_NAMES::ATT_WEDGETEXTURE])
1474 				{
1475 					glDisable(GL_TEXTURE_2D);
1476 					glDrawArrays(GL_TRIANGLES, 0, _mesh.fn * 3);
1477 				}
1478 				else
1479 				{
1480 					glEnable(GL_TEXTURE_2D);
1481 					for (std::vector< std::pair<short, GLuint> >::const_iterator it = _texindnumtriangles.begin(); it != _texindnumtriangles.end(); ++it)
1482 					{
1483 						if ((int(it->first) != -1) && (size_t(it->first) < textureindex.size()))
1484 							glBindTexture(GL_TEXTURE_2D, textureindex[it->first]);
1485 						else
1486 							glBindTexture(GL_TEXTURE_2D, 0);
1487 						glDrawArrays(GL_TRIANGLES, firsttriangleoffset, it->second * 3 - firsttriangleoffset);
1488 						firsttriangleoffset = it->second * 3;
1489 					}
1490 					glBindTexture(GL_TEXTURE_2D, 0);
1491 					glDisable(GL_TEXTURE_2D);
1492 				}
1493 
1494 			}
1495 			else
1496 			{
1497 				if (req[INT_ATT_NAMES::ATT_VERTTEXTURE])
1498 				{
1499 					if (textureindex.size() > 0)
1500 					{
1501 						glEnable(GL_TEXTURE_2D);
1502 						glBindTexture(GL_TEXTURE_2D, textureindex[0]);
1503 					}
1504 				}
1505 				else
1506 					glDisable(GL_TEXTURE_2D);
1507 
1508 				if (_bo[INT_ATT_NAMES::ATT_VERTINDICES]->_isvalid)
1509 				{
1510 					//qDebug("Indexed drawing");
1511 					glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _bo[INT_ATT_NAMES::ATT_VERTINDICES]->_bohandle);
1512 					glDrawElements(GL_TRIANGLES, GLsizei(_mesh.FN() * _bo[INT_ATT_NAMES::ATT_VERTINDICES]->_components), GL_UNSIGNED_INT, NULL);
1513 					glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1514 
1515 				}
1516 
1517 				glBindTexture(GL_TEXTURE_2D, 0);
1518 				glDisable(GL_TEXTURE_2D);
1519 			}
1520 			InternalRendAtts tmp;
1521 			updateClientState(tmp);
1522 			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1523 			glBindBuffer(GL_ARRAY_BUFFER, 0);
1524 		}
1525 
1526 		void drawTrianglesIM(const InternalRendAtts& req, const std::vector<GLuint>& textureindex = std::vector<GLuint>()) const
1527 		{
1528 			if (_mesh.fn == 0)
1529 				return;
1530 
1531 			bool vn = req[INT_ATT_NAMES::ATT_VERTNORMAL] && vcg::tri::HasPerVertexNormal(_mesh);
1532 			bool fn = req[INT_ATT_NAMES::ATT_FACENORMAL] && vcg::tri::HasPerFaceNormal(_mesh);
1533 			bool vc = req[INT_ATT_NAMES::ATT_VERTCOLOR] && vcg::tri::HasPerVertexColor(_mesh);
1534 			bool fc = req[INT_ATT_NAMES::ATT_FACECOLOR] && vcg::tri::HasPerFaceColor(_mesh);
1535 			bool vt = req[INT_ATT_NAMES::ATT_VERTTEXTURE] && vcg::tri::HasPerVertexTexCoord(_mesh);
1536 			bool wt = req[INT_ATT_NAMES::ATT_WEDGETEXTURE] && vcg::tri::HasPerWedgeTexCoord(_mesh);
1537 
1538 
1539 			//typename MESHTYPE::FaceContainer::iterator fp;
1540 			typename MESH_TYPE::FaceIterator fi = _mesh.face.begin();
1541 
1542 			short curtexname = -1;
1543 			if (wt)
1544 			{
1545 				curtexname = (*fi).WT(0).n();
1546 				if ((curtexname >= 0) && (curtexname < (int)textureindex.size()))
1547 				{
1548 					glEnable(GL_TEXTURE_2D);
1549 					glBindTexture(GL_TEXTURE_2D, textureindex[curtexname]);
1550 				}
1551 				else
1552 				{
1553 					glDisable(GL_TEXTURE_2D);
1554 				}
1555 			}
1556 
1557 			if (vt && !textureindex.empty()) // in the case of per vertex tex coord we assume that we have a SINGLE texture.
1558 			{
1559 				curtexname = 0;
1560 				glEnable(GL_TEXTURE_2D);
1561 				glBindTexture(GL_TEXTURE_2D, textureindex[curtexname]);
1562 			}
1563 
1564 			glBegin(GL_TRIANGLES);
1565 
1566 			while (fi != _mesh.face.end())
1567 			{
1568 				typename MESH_TYPE::FaceType & f = *fi;
1569 				if (!f.IsD())
1570 				{
1571 					if (wt)
1572 						if (f.WT(0).n() != curtexname)
1573 						{
1574 							curtexname = (*fi).WT(0).n();
1575 							glEnd();
1576 
1577 							if (curtexname >= 0)
1578 							{
1579 								glEnable(GL_TEXTURE_2D);
1580 								if (!textureindex.empty())
1581 									glBindTexture(GL_TEXTURE_2D, textureindex[curtexname]);
1582 							}
1583 							else
1584 							{
1585 								glDisable(GL_TEXTURE_2D);
1586 							}
1587 
1588 							glBegin(GL_TRIANGLES);
1589 						}
1590 
1591 					if (fn)
1592 						glNormal(f.cN());
1593 					if (vn)
1594 						glNormal(f.V(0)->cN());
1595 
1596 					if (fc)
1597 						glColor(f.C());
1598 					if (vc)
1599 						glColor(f.V(0)->C());
1600 					if (vt)
1601 						glTexCoord(f.V(0)->T().P());
1602 					if (wt)
1603 						glTexCoord(f.WT(0).t(0));
1604 					glVertex(f.V(0)->P());
1605 
1606 					if (vn)
1607 						glNormal(f.V(1)->cN());
1608 					if (vc)
1609 						glColor(f.V(1)->C());
1610 					if (vt)
1611 						glTexCoord(f.V(1)->T().P());
1612 					if (wt)
1613 						glTexCoord(f.WT(1).t(0));
1614 					glVertex(f.V(1)->P());
1615 
1616 					if (vn)
1617 						glNormal(f.V(2)->cN());
1618 					if (vc)
1619 						glColor(f.V(2)->C());
1620 					if (vt)
1621 						glTexCoord(f.V(2)->T().P());
1622 					if (wt)
1623 						glTexCoord(f.WT(2).t(0));
1624 					glVertex(f.V(2)->P());
1625 				}
1626 				++fi;
1627 			}
1628 
1629 			glEnd();
1630 		}
1631 
1632 		void drawPoints(const InternalRendAtts& req, GL_OPTIONS_DERIVED_TYPE* glopts, const std::vector<GLuint>& textureindex = std::vector<GLuint>()) const
1633 		{
1634 			if (_mesh.VN() == 0)
1635 				return;
1636 			glPushAttrib(GL_ALL_ATTRIB_BITS);
1637 
1638 
1639 			bool isgloptsvalid = (glopts != NULL);
1640 
1641 
1642 			if ((isgloptsvalid && glopts->_perpoint_noshading) || (isgloptsvalid && glopts->_perpoint_dot_enabled))
1643 				glDisable(GL_LIGHTING);
1644 			else
1645 				if ((!isgloptsvalid) || req[INT_ATT_NAMES::ATT_VERTNORMAL])
1646 				{
1647 					glEnable(GL_LIGHTING);
1648 				}
1649 
1650 			glEnable(GL_COLOR_MATERIAL);
1651 			if ((isgloptsvalid) && ((glopts->_perpoint_fixed_color_enabled) || (glopts->_perpoint_mesh_color_enabled))) {
1652 				if (glopts->_perpoint_fixed_color_enabled)
1653 					glColor(glopts->_perpoint_fixed_color);
1654 				else
1655 					glColor(_mesh.C());
1656 			}
1657 
1658 			if (req[INT_ATT_NAMES::ATT_VERTCOLOR])
1659 				glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
1660 
1661 
1662 			if (req[INT_ATT_NAMES::ATT_VERTTEXTURE])
1663 			{
1664 				glEnable(GL_TEXTURE_2D);
1665 				if (textureindex.size() > 0)
1666 					glBindTexture(GL_TEXTURE_2D, textureindex[0]);
1667 				else
1668 					glBindTexture(GL_TEXTURE_2D, 0);
1669 			}
1670 			else
1671 				glDisable(GL_TEXTURE_2D);
1672 			//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _bo[GLMeshAttributesInfo::ATT_VERTINDEX]->_bohandle);
1673 
1674 			if (glopts != NULL)
1675 			{
1676 				if (!glopts->_perpoint_dot_enabled)
1677 					glPointSize(glopts->_perpoint_pointsize);
1678 				if ((glopts->_perpoint_pointsmooth_enabled) || (glopts->_perpoint_dot_enabled))
1679 					glEnable(GL_POINT_SMOOTH);
1680 				else
1681 					glDisable(GL_POINT_SMOOTH);
1682 				if (glopts->_perpoint_pointattenuation_enabled)
1683 				{
1684 					vcg::Matrix44<typename MESH_TYPE::ScalarType> mat;
1685 					glGetv(GL_MODELVIEW_MATRIX, mat);
1686 					vcg::Point3<typename MESH_TYPE::ScalarType> c = _mesh.bbox.Center();
1687 					float camDist = (float)Norm(mat*c);
1688 					float quadratic[] = { 0.0f, 0.0f, 1.0f / (camDist*camDist) , 0.0f };
1689 					glPointParameterfv(GL_POINT_DISTANCE_ATTENUATION, quadratic);
1690 					glPointParameterf(GL_POINT_SIZE_MAX, 16.0f);
1691 					glPointParameterf(GL_POINT_SIZE_MIN, 1.0f);
1692 				}
1693 				else
1694 				{
1695 					float quadratic[] = { 1.0f, 0.0f, 0.0f };
1696 					glPointParameterfv(GL_POINT_DISTANCE_ATTENUATION, quadratic);
1697 					float pointsize = 1.0f;
1698 					if (isgloptsvalid)
1699 						pointsize = glopts->_perpoint_pointsize;
1700 					glPointSize(pointsize);
1701 				}
1702 				if (glopts->_perpoint_dot_enabled)
1703 				{
1704 					glEnable(GL_BLEND);
1705 					glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1706 					glDepthRange(0.0, 0.9999);
1707 					glDepthFunc(GL_LEQUAL);
1708 					glPointSize(glopts->_perpoint_pointsize + 0.5);
1709 				}
1710 			}
1711 			if (isBORenderingAvailable())
1712 				drawPointsBO(req);
1713 			else
1714 				drawPointsIM(req);
1715 
1716 			if ((glopts != NULL) && (glopts->_perpoint_dot_enabled))
1717 			{
1718 				float psize = 0.0001f;
1719 				if ((glopts->_perpoint_pointsize - 1) > 0)
1720 					psize = (glopts->_perpoint_pointsize - 1);
1721 				glPointSize(psize);
1722 				if (isBORenderingAvailable())
1723 					drawPointsBO(req);
1724 				else
1725 					drawPointsIM(req);
1726 			}
1727 			glPopAttrib();
1728 		}
1729 
drawPointsBO(const InternalRendAtts & req)1730 		void drawPointsBO(const InternalRendAtts& req) const
1731 		{
1732 			size_t pointsnum = _mesh.VN();
1733 			if (InternalRendAtts::replicatedPipelineNeeded(_currallocatedboatt))
1734 				pointsnum = _mesh.FN() * 3;
1735 			updateClientState(req);
1736 			glDrawArrays(GL_POINTS, 0, GLsizei(pointsnum));
1737 			/*disable all client state buffers*/
1738 			InternalRendAtts tmp;
1739 			updateClientState(tmp);
1740 		}
1741 
drawPointsIM(const InternalRendAtts & req)1742 		void drawPointsIM(const InternalRendAtts& req) const
1743 		{
1744 			bool vn = req[INT_ATT_NAMES::ATT_VERTNORMAL] && vcg::tri::HasPerVertexNormal(_mesh);
1745 			bool vc = req[INT_ATT_NAMES::ATT_VERTCOLOR] && vcg::tri::HasPerVertexColor(_mesh);
1746 			bool vt = req[INT_ATT_NAMES::ATT_VERTTEXTURE] && vcg::tri::HasPerVertexTexCoord(_mesh);
1747 
1748 
1749 			glBegin(GL_POINTS);
1750 			for (typename MESH_TYPE::VertexIterator vi = _mesh.vert.begin(); vi != _mesh.vert.end(); ++vi)
1751 			{
1752 				if (!(*vi).IsD())
1753 				{
1754 					if (vn) glNormal((*vi).cN());
1755 					if (vc) glColor((*vi).C());
1756 					if (vt) glTexCoord((*vi).T().P());
1757 					glVertex((*vi).P());
1758 				}
1759 			}
1760 			glEnd();
1761 		}
1762 
drawEdges(const InternalRendAtts & req,GL_OPTIONS_DERIVED_TYPE * glopts)1763 		void drawEdges(const InternalRendAtts& req, GL_OPTIONS_DERIVED_TYPE* glopts) const
1764 		{
1765 			if (_mesh.VN() == 0)
1766 				return;
1767 			glPushAttrib(GL_ALL_ATTRIB_BITS);
1768 
1769 			bool isgloptsvalid = (glopts != NULL);
1770 
1771 			glEnable(GL_COLOR_MATERIAL);
1772 			glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
1773 
1774 			if (isgloptsvalid && glopts->_perwire_noshading)
1775 				glDisable(GL_LIGHTING);
1776 			else
1777 				if ((!isgloptsvalid) || (req[INT_ATT_NAMES::ATT_VERTNORMAL]))
1778 				{
1779 					glEnable(GL_LIGHTING);
1780 				}
1781 
1782 			bool colordefinedenabled = (isgloptsvalid) && ((glopts->_perwire_fixed_color_enabled) || (glopts->_perwire_mesh_color_enabled));
1783 
1784 			if (!(isgloptsvalid) || colordefinedenabled)
1785 			{
1786 				vcg::Color4b tmpcol = vcg::Color4b(vcg::Color4b::DarkGray);
1787 				if (colordefinedenabled)
1788 				{
1789 					if (glopts->_perwire_fixed_color_enabled)
1790 						tmpcol = glopts->_perwire_fixed_color;
1791 					else
1792 						tmpcol = _mesh.cC();
1793 				}
1794 				glColor(tmpcol);
1795 			}
1796 
1797 			glDisable(GL_TEXTURE_2D);
1798 			//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _bo[GLMeshAttributesInfo::ATT_VERTINDEX]->_bohandle);
1799 
1800 			float linewidth = 1.0f;
1801 			if (isgloptsvalid)
1802 				linewidth = glopts->_perwire_wirewidth;
1803 			glLineWidth(linewidth);
1804 
1805 			if (isBORenderingAvailable())
1806 				drawEdgesBO(req);
1807 			else
1808 				drawEdgesIM(req);
1809 			//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1810 
1811 			/*disable all client state buffers*/
1812 			glPopAttrib();
1813 		}
1814 
drawEdgesBO(const InternalRendAtts & req)1815 		void drawEdgesBO(const InternalRendAtts& req) const
1816 		{
1817 			if (_bo[INT_ATT_NAMES::ATT_EDGEINDICES]->_isvalid)
1818 			{
1819 				//qDebug("Indexed drawing");
1820 				updateClientState(req);
1821 				glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _bo[INT_ATT_NAMES::ATT_EDGEINDICES]->_bohandle);
1822 				glDrawElements(GL_LINES, GLsizei(_edge.size() * _bo[INT_ATT_NAMES::ATT_EDGEINDICES]->_components), GL_UNSIGNED_INT, NULL);
1823 				glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1824 				InternalRendAtts tmp;
1825 				updateClientState(tmp);
1826 			}
1827 		}
1828 
drawEdgesIM(const InternalRendAtts & req)1829 		void drawEdgesIM(const InternalRendAtts& req) const
1830 		{
1831 			typename MESH_TYPE::FaceIterator fi = _mesh.face.begin();
1832 
1833 			bool vn = req[INT_ATT_NAMES::ATT_VERTNORMAL] && vcg::tri::HasPerVertexNormal(_mesh);
1834 			bool vc = req[INT_ATT_NAMES::ATT_VERTCOLOR] && vcg::tri::HasPerVertexColor(_mesh);
1835 
1836 			glBegin(GL_LINES);
1837 
1838 			while (fi != _mesh.face.end())
1839 			{
1840 				typename MESH_TYPE::FaceType & f = *fi;
1841 
1842 				if (!f.IsD())
1843 				{
1844 					if (!f.IsF(0))
1845 					{
1846 						if (vn)	glNormal(f.V(0)->cN());
1847 						if (vc)	glColor(f.V(0)->C());
1848 						glVertex(f.V(0)->P());
1849 
1850 						if (vn)	glNormal(f.V(1)->cN());
1851 
1852 						if (vc)	glColor(f.V(1)->C());
1853 						glVertex(f.V(1)->P());
1854 					}
1855 
1856 					if (!f.IsF(1))
1857 					{
1858 						if (vn)	glNormal(f.V(1)->cN());
1859 						if (vc)	glColor(f.V(1)->C());
1860 						glVertex(f.V(1)->P());
1861 
1862 						if (vn)	glNormal(f.V(2)->cN());
1863 						if (vc)	glColor(f.V(2)->C());
1864 						glVertex(f.V(2)->P());
1865 					}
1866 
1867 					if (!f.IsF(2))
1868 					{
1869 						if (vn)	glNormal(f.V(2)->cN());
1870 						if (vc)	glColor(f.V(2)->C());
1871 						glVertex(f.V(2)->P());
1872 
1873 						if (vn)	glNormal(f.V(0)->cN());
1874 						if (vc)	glColor(f.V(0)->C());
1875 						glVertex(f.V(0)->P());
1876 					}
1877 
1878 				}
1879 				++fi;
1880 			}
1881 
1882 			glEnd();
1883 		}
1884 
drawBBox(GL_OPTIONS_DERIVED_TYPE * glopts)1885 		void drawBBox(GL_OPTIONS_DERIVED_TYPE* glopts) const
1886 		{
1887 			glPushAttrib(GL_ALL_ATTRIB_BITS);
1888 			bool isgloptsvalid = (glopts != NULL);
1889 
1890 			glDisable(GL_LIGHTING);
1891 			glEnable(GL_COLOR_MATERIAL);
1892 			glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
1893 
1894 			if ((isgloptsvalid) && (glopts->_perbbox_fixed_color_enabled))
1895 				glColor(glopts->_perbbox_fixed_color);
1896 			else
1897 			{
1898 				if ((isgloptsvalid) && (glopts->_perbbox_mesh_color_enabled))
1899 					glColor(_mesh.C());
1900 				else
1901 					glColor(vcg::Color4b(vcg::Color4b::White));
1902 			}
1903 			if (isBORenderingAvailable())
1904 				drawBBoxBO();
1905 			else
1906 				drawBBoxIM();
1907 			glPopAttrib();
1908 		}
1909 
drawBBoxBO()1910 		void drawBBoxBO() const
1911 		{
1912 			vcg::Box3<typename MESH_TYPE::ScalarType>& b = _mesh.bbox;
1913 
1914 			GLuint bbhandle;
1915 			glGenBuffers(1, &bbhandle);
1916 			std::vector<vcg::Point3f> bbox(12 * 2);
1917 
1918 			//0
1919 			bbox[0] = vcg::Point3f((float)b.min[0], (float)b.min[1], (float)b.min[2]);
1920 			bbox[1] = vcg::Point3f((float)b.max[0], (float)b.min[1], (float)b.min[2]);
1921 
1922 			//1
1923 			bbox[2] = vcg::Point3f((float)b.max[0], (float)b.min[1], (float)b.min[2]);
1924 			bbox[3] = vcg::Point3f((float)b.max[0], (float)b.max[1], (float)b.min[2]);
1925 
1926 			//2
1927 			bbox[4] = vcg::Point3f((float)b.max[0], (float)b.max[1], (float)b.min[2]);
1928 			bbox[5] = vcg::Point3f((float)b.min[0], (float)b.max[1], (float)b.min[2]);
1929 
1930 			//3
1931 			bbox[6] = vcg::Point3f((float)b.min[0], (float)b.max[1], (float)b.min[2]);
1932 			bbox[7] = vcg::Point3f((float)b.min[0], (float)b.min[1], (float)b.min[2]);
1933 
1934 			//4
1935 			bbox[8] = vcg::Point3f((float)b.min[0], (float)b.min[1], (float)b.min[2]);
1936 			bbox[9] = vcg::Point3f((float)b.min[0], (float)b.min[1], (float)b.max[2]);
1937 
1938 			//5
1939 			bbox[10] = vcg::Point3f((float)b.min[0], (float)b.min[1], (float)b.max[2]);
1940 			bbox[11] = vcg::Point3f((float)b.max[0], (float)b.min[1], (float)b.max[2]);
1941 
1942 			//6
1943 			bbox[12] = vcg::Point3f((float)b.max[0], (float)b.min[1], (float)b.max[2]);
1944 			bbox[13] = vcg::Point3f((float)b.max[0], (float)b.min[1], (float)b.min[2]);
1945 
1946 			//7
1947 			bbox[14] = vcg::Point3f((float)b.max[0], (float)b.min[1], (float)b.max[2]);
1948 			bbox[15] = vcg::Point3f((float)b.max[0], (float)b.max[1], (float)b.max[2]);
1949 
1950 			//8
1951 			bbox[16] = vcg::Point3f((float)b.max[0], (float)b.max[1], (float)b.max[2]);
1952 			bbox[17] = vcg::Point3f((float)b.max[0], (float)b.max[1], (float)b.min[2]);
1953 
1954 			//9
1955 			bbox[18] = vcg::Point3f((float)b.max[0], (float)b.max[1], (float)b.max[2]);
1956 			bbox[19] = vcg::Point3f((float)b.min[0], (float)b.max[1], (float)b.max[2]);
1957 
1958 			//10
1959 			bbox[20] = vcg::Point3f((float)b.min[0], (float)b.max[1], (float)b.max[2]);
1960 			bbox[21] = vcg::Point3f((float)b.min[0], (float)b.min[1], (float)b.max[2]);
1961 
1962 			//11
1963 			bbox[22] = vcg::Point3f((float)b.min[0], (float)b.max[1], (float)b.max[2]);
1964 			bbox[23] = vcg::Point3f((float)b.min[0], (float)b.max[1], (float)b.min[2]);
1965 
1966 			glBindBuffer(GL_ARRAY_BUFFER, bbhandle);
1967 			glBufferData(GL_ARRAY_BUFFER, 12 * 2 * sizeof(vcg::Point3f), &(bbox[0]), GL_STATIC_DRAW);
1968 			glVertexPointer(3, GL_FLOAT, 0, 0);
1969 			glBindBuffer(GL_ARRAY_BUFFER, 0);
1970 			glEnableClientState(GL_VERTEX_ARRAY);
1971 			glDrawArrays(GL_LINES, 0, 24);
1972 			glDisableClientState(GL_VERTEX_ARRAY);
1973 			glDeleteBuffers(1, &bbhandle);
1974 		}
1975 
drawBBoxIM()1976 		void drawBBoxIM() const
1977 		{
1978 			vcg::Box3<typename MESH_TYPE::ScalarType>& b = _mesh.bbox;
1979 
1980 			glBegin(GL_LINE_STRIP);
1981 			glVertex3f((float)b.min[0], (float)b.min[1], (float)b.min[2]);
1982 			glVertex3f((float)b.max[0], (float)b.min[1], (float)b.min[2]);
1983 			glVertex3f((float)b.max[0], (float)b.max[1], (float)b.min[2]);
1984 			glVertex3f((float)b.min[0], (float)b.max[1], (float)b.min[2]);
1985 			glVertex3f((float)b.min[0], (float)b.min[1], (float)b.min[2]);
1986 			glEnd();
1987 			glBegin(GL_LINE_STRIP);
1988 			glVertex3f((float)b.min[0], (float)b.min[1], (float)b.max[2]);
1989 			glVertex3f((float)b.max[0], (float)b.min[1], (float)b.max[2]);
1990 			glVertex3f((float)b.max[0], (float)b.max[1], (float)b.max[2]);
1991 			glVertex3f((float)b.min[0], (float)b.max[1], (float)b.max[2]);
1992 			glVertex3f((float)b.min[0], (float)b.min[1], (float)b.max[2]);
1993 			glEnd();
1994 			glBegin(GL_LINES);
1995 			glVertex3f((float)b.min[0], (float)b.min[1], (float)b.min[2]);
1996 			glVertex3f((float)b.min[0], (float)b.min[1], (float)b.max[2]);
1997 
1998 			glVertex3f((float)b.max[0], (float)b.min[1], (float)b.min[2]);
1999 			glVertex3f((float)b.max[0], (float)b.min[1], (float)b.max[2]);
2000 
2001 			glVertex3f((float)b.max[0], (float)b.max[1], (float)b.min[2]);
2002 			glVertex3f((float)b.max[0], (float)b.max[1], (float)b.max[2]);
2003 
2004 			glVertex3f((float)b.min[0], (float)b.max[1], (float)b.min[2]);
2005 			glVertex3f((float)b.min[0], (float)b.max[1], (float)b.max[2]);
2006 			glEnd();
2007 		}
2008 
updateClientState(const InternalRendAtts & req)2009 		void updateClientState(const InternalRendAtts& req) const
2010 		{
2011 			int ii = 0;
2012 			for (typename std::vector<GLBufferObject*>::const_iterator it = _bo.begin(); it != _bo.end(); ++it)
2013 			{
2014 				INT_ATT_NAMES boname(ii);
2015 				if ((boname != INT_ATT_NAMES::ATT_VERTINDICES) && (boname != INT_ATT_NAMES::ATT_EDGEINDICES) /*&& (boname != INT_ATT_NAMES::ATT_FIXEDCOLOR)*/)
2016 				{
2017 					if (req[boname] && _currallocatedboatt[boname] && (*it != NULL))
2018 					{
2019 						glBindBuffer((*it)->_target, (*it)->_bohandle);
2020 						setBufferPointer(boname);
2021 						glEnableClientState((*it)->_clientstatetag);
2022 						glBindBuffer((*it)->_target, 0);
2023 					}
2024 					else
2025 					{
2026 						glBindBuffer((*it)->_target, (*it)->_bohandle);
2027 						disableClientState(boname, req);
2028 						glBindBuffer((*it)->_target, 0);
2029 					}
2030 				}
2031 				++ii;
2032 			}
2033 		}
2034 
setBufferPointer(INT_ATT_NAMES boname)2035 		void setBufferPointer(INT_ATT_NAMES boname) const
2036 		{
2037 			unsigned int ii = boname;
2038 			if (ii >= INT_ATT_NAMES::enumArity())
2039 				return;
2040 			GLBufferObject* cbo = _bo[ii];
2041 			if (cbo == NULL)
2042 				return;
2043 
2044 			switch (ii)
2045 			{
2046 			case(INT_ATT_NAMES::ATT_VERTPOSITION):
2047 			{
2048 				glVertexPointer(GLint(cbo->_components), cbo->_gltype, GLsizei(0), 0);
2049 				break;
2050 			}
2051 			case(INT_ATT_NAMES::ATT_VERTNORMAL):
2052 			case(INT_ATT_NAMES::ATT_FACENORMAL):
2053 			{
2054 				glNormalPointer(cbo->_gltype, GLsizei(0), 0);
2055 				break;
2056 			}
2057 			case(INT_ATT_NAMES::ATT_VERTCOLOR):
2058 			case(INT_ATT_NAMES::ATT_FACECOLOR):
2059 			{
2060 				glColorPointer(GLint(cbo->_components), cbo->_gltype, GLsizei(0), 0);
2061 				break;
2062 			}
2063 			case(INT_ATT_NAMES::ATT_VERTTEXTURE):
2064 			case(INT_ATT_NAMES::ATT_WEDGETEXTURE):
2065 			{
2066 				glTexCoordPointer(GLint(cbo->_components), cbo->_gltype, GLsizei(0), 0);
2067 				break;
2068 			}
2069 			default: break;
2070 			}
2071 		}
2072 
disableClientState(INT_ATT_NAMES boname,const RendAtts & req)2073 		void disableClientState(INT_ATT_NAMES boname, const RendAtts& req) const
2074 		{
2075 
2076 			if (boname >= INT_ATT_NAMES::enumArity())
2077 				return;
2078 
2079 			switch (boname)
2080 			{
2081 			case(INT_ATT_NAMES::ATT_VERTPOSITION):
2082 			{
2083 				glDisableClientState(GL_VERTEX_ARRAY);
2084 				break;
2085 			}
2086 			case(INT_ATT_NAMES::ATT_VERTNORMAL):
2087 			case(INT_ATT_NAMES::ATT_FACENORMAL):
2088 			{
2089 				if (!req[INT_ATT_NAMES::ATT_VERTNORMAL] && !req[INT_ATT_NAMES::ATT_FACENORMAL])
2090 					glDisableClientState(GL_NORMAL_ARRAY);
2091 				break;
2092 			}
2093 			case(INT_ATT_NAMES::ATT_VERTCOLOR):
2094 			case(INT_ATT_NAMES::ATT_FACECOLOR):
2095 			{
2096 				if (!req[INT_ATT_NAMES::ATT_VERTCOLOR] && !req[INT_ATT_NAMES::ATT_FACECOLOR])
2097 					glDisableClientState(GL_COLOR_ARRAY);
2098 				break;
2099 			}
2100 			case(INT_ATT_NAMES::ATT_VERTTEXTURE):
2101 			case(INT_ATT_NAMES::ATT_WEDGETEXTURE):
2102 			{
2103 				if (!req[INT_ATT_NAMES::ATT_VERTTEXTURE] && !req[INT_ATT_NAMES::ATT_WEDGETEXTURE])
2104 					glDisableClientState(GL_TEXTURE_COORD_ARRAY);
2105 				break;
2106 			}
2107 			default:
2108 			{
2109 				break;
2110 			}
2111 
2112 			}
2113 		}
2114 
fillchunkMap()2115 		void fillchunkMap()
2116 		{
2117 			_chunkmap.clear();
2118 			if (!vcg::tri::HasPerWedgeTexCoord(_mesh) || _mesh.face.size() == 0)
2119 				return;
2120 			typename MESH_TYPE::FaceIterator infrange = _mesh.face.begin();
2121 			short texind = _mesh.face[0].WT(0).N();
2122 			for (typename MESH_TYPE::FaceIterator fit = _mesh.face.begin(); fit != _mesh.face.end(); ++fit)
2123 			{
2124 				bool last = (fit == (_mesh.face.end() - 1));
2125 				if (fit->WT(0).N() != texind || last)
2126 				{
2127 					int lowind = std::distance(_mesh.face.begin(), infrange);
2128 					int topind = std::distance(_mesh.face.begin(), fit) - 1;
2129 					if (last)
2130 						topind++;
2131 					_chunkmap[texind].push_back(std::make_pair((GLuint)lowind, (GLuint)topind));
2132 					infrange = fit;
2133 					texind = fit->WT(0).N();
2134 				}
2135 			}
2136 		}
2137 
debug(const InternalRendAtts & tobeallocated,const InternalRendAtts & tobedeallocated,const InternalRendAtts & tobeupdated)2138 		void debug(const InternalRendAtts& tobeallocated, const InternalRendAtts& tobedeallocated, const InternalRendAtts& tobeupdated)
2139 		{
2140 			_loginfo.reset();
2141 			_loginfo._tobedeallocated = std::string("to_be_deallocated: ");
2142 			_loginfo._tobeallocated = std::string("to_be_allocated: ");
2143 			_loginfo._tobeupdated = std::string("to_be_updated: ");
2144 
2145 			std::string truestring("true");
2146 			std::string falsestring("false");
2147 			for (unsigned int ii = 0; ii < INT_ATT_NAMES::enumArity(); ++ii)
2148 			{
2149 				std::string deallocres(falsestring);
2150 				if (tobedeallocated[ii])
2151 					deallocres = truestring;
2152 				_loginfo._tobedeallocated += deallocres + " ";
2153 
2154 				std::string allocres(falsestring);
2155 				if (tobeallocated[ii])
2156 					allocres = truestring;
2157 				_loginfo._tobeallocated += allocres + " ";
2158 
2159 				std::string upres(falsestring);
2160 				if (tobeupdated[ii])
2161 					upres = truestring;
2162 				_loginfo._tobeupdated += upres + " ";
2163 			}
2164 
2165 			_loginfo._tobedeallocated = std::string("[") + _loginfo._tobedeallocated + std::string("]");
2166 			_loginfo._tobeallocated = std::string("[") + _loginfo._tobeallocated + std::string("]");
2167 			_loginfo._tobeupdated = std::string("[") + _loginfo._tobeupdated + std::string("]");
2168 
2169 
2170 			int hh = 0;
2171 
2172 			for (typename ViewsMap::const_iterator it = _perviewreqatts.begin(); it != _perviewreqatts.end(); ++it)
2173 			{
2174 				std::stringstream tmpstream;
2175 				tmpstream << "view_" << hh << ":\n";
2176 				for (size_t pm = 0; pm < size_t(PR_ARITY); ++pm)
2177 				{
2178 					tmpstream << DebugInfo::primitiveName(pm) << " ";
2179 
2180 					for (unsigned int ii = 0; ii < INT_ATT_NAMES::enumArity(); ++ii)
2181 					{
2182 						std::string res = falsestring;
2183 						if (it->second._intatts[pm][ii])
2184 							res = truestring;
2185 						tmpstream << "att[" << ii << "]=" << res << " ";
2186 					}
2187 					tmpstream << std::endl;
2188 				}
2189 				_loginfo._perviewdata.push_back(tmpstream.str());
2190 				++hh;
2191 			}
2192 
2193 			std::stringstream tmpstream;
2194 			tmpstream << "currently_allocated: ";
2195 			for (unsigned int ii = 0; ii < INT_ATT_NAMES::enumArity(); ++ii)
2196 			{
2197 				std::string res = falsestring;
2198 				if (_currallocatedboatt[ii])
2199 					res = truestring;
2200 				tmpstream << "att[" << ii << "]=" << res << " ";
2201 			}
2202 			_loginfo._currentlyallocated = tmpstream.str();
2203 		}
2204 
2205 		class EdgeVertInd
2206 		{
2207 		public:
2208 
2209 			GLuint  _v[2];  // the two Vertex indices are ordered!
2210 
EdgeVertInd()2211 			EdgeVertInd() {}
EdgeVertInd(const MESH_TYPE & m,typename MESH_TYPE::FacePointer pf,const int nz)2212 			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)2213 			EdgeVertInd(const MESH_TYPE& m, typename MESH_TYPE::EdgePointer  pe, const int nz) { this->set(m, pe, nz); }
2214 
set(const MESH_TYPE & m,typename MESH_TYPE::FacePointer pf,const int nz)2215 			void set(const MESH_TYPE& m, typename MESH_TYPE::FacePointer  pf, const int nz)
2216 			{
2217 				assert(pf != 0);
2218 				assert(nz >= 0);
2219 				assert(nz < pf->VN());
2220 
2221 				_v[0] = GLuint(vcg::tri::Index(m, pf->V(nz)));;
2222 				_v[1] = GLuint(vcg::tri::Index(m, pf->V(pf->Next(nz))));
2223 				assert(_v[0] != _v[1]); // The face pointed by 'f' is Degenerate (two coincident vertexes)
2224 
2225 				if (_v[0] > _v[1])
2226 					std::swap(_v[0], _v[1]);
2227 			}
2228 
set(const MESH_TYPE & m,typename MESH_TYPE::EdgePointer pe,const int nz)2229 			void set(const MESH_TYPE& m, typename MESH_TYPE::EdgePointer pe, const int nz)
2230 			{
2231 				assert(pe != 0);
2232 				assert(nz >= 0);
2233 				assert(nz < 2);
2234 
2235 				_v[0] = GLuint(vcg::tri::Index(m, pe->V(nz)));;
2236 				_v[1] = GLuint(vcg::tri::Index(m, pe->V((nz + 1) % 2)));
2237 				assert(_v[0] != _v[1]); // The face pointed by 'f' is Degenerate (two coincident vertexes)
2238 
2239 				if (_v[0] > _v[1])
2240 					std::swap(_v[0], _v[1]);
2241 			}
2242 
2243 			inline bool operator<(const EdgeVertInd& pe) const
2244 			{
2245 				if (_v[0] < pe._v[0])
2246 					return true;
2247 				else if (_v[0] > pe._v[0])
2248 					return false;
2249 				else
2250 					return _v[1] < pe._v[1];
2251 			}
2252 
2253 			inline bool operator==(const EdgeVertInd & pe) const
2254 			{
2255 				return _v[0] == pe._v[0] && _v[1] == pe._v[1];
2256 			}
2257 		};
2258 
2259 		static void fillEdgeVector(MESH_TYPE &m, std::vector<EdgeVertInd> &edgeVec, bool includeFauxEdge = true)
2260 		{
2261 			if (m.FN() > 0)
2262 			{
2263 				edgeVec.reserve(m.FN() * 3);
2264 				for (typename MESH_TYPE::FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
2265 					if (!(*fi).IsD())
2266 						for (int j = 0; j < (*fi).VN(); ++j)
2267 							if (includeFauxEdge || !(*fi).IsF(j))
2268 								edgeVec.push_back(EdgeVertInd(m, &*fi, j));
2269 			}
2270 			else
2271 				if ((m.VN() > 0) && (m.EN() > 0))
2272 				{
2273 					edgeVec.reserve(m.EN() * 2);
2274 					for (typename MESH_TYPE::EdgeIterator ei = m.edge.begin(); ei != m.edge.end(); ++ei)
2275 						if (!(*ei).IsD())
2276 							for (int j = 0; j < 2; ++j)
2277 								edgeVec.push_back(EdgeVertInd(m, &*ei, j));
2278 				}
2279 
2280 		}
2281 
fillUniqueEdgeVector(MESH_TYPE & m,std::vector<EdgeVertInd> & edgeVec)2282 		static void fillUniqueEdgeVector(MESH_TYPE &m, std::vector<EdgeVertInd> &edgeVec)
2283 		{
2284 			fillEdgeVector(m, edgeVec, false);
2285 			std::sort(edgeVec.begin(), edgeVec.end());
2286 
2287 			typename std::vector<EdgeVertInd>::iterator newEnd = std::unique(edgeVec.begin(), edgeVec.end());
2288 
2289 			edgeVec.resize(newEnd - edgeVec.begin());
2290 		}
2291 
2292 		struct GLBufferObject
2293 		{
GLBufferObjectGLBufferObject2294 			GLBufferObject(size_t components, GLenum gltype, GLenum clientstatetag, GLenum target)
2295 				:_size(0), _components(components), _isvalid(false), _gltype(gltype), _target(target), _clientstatetag(clientstatetag), _bohandle(0)
2296 			{
2297 			}
2298 
GLBufferObjectGLBufferObject2299 			GLBufferObject(size_t components, GLenum gltype, GLenum target)
2300 				:_size(0), _components(components), _isvalid(false), _gltype(gltype), _target(target), _clientstatetag(), _bohandle(0)
2301 			{
2302 			}
2303 
getSizeOfGLTypeGLBufferObject2304 			size_t getSizeOfGLType() const
2305 			{
2306 				switch (_gltype)
2307 				{
2308 				case(GL_FLOAT):
2309 					return sizeof(GLfloat);
2310 				case(GL_INT):
2311 					return sizeof(GLint);
2312 				case(GL_UNSIGNED_INT):
2313 					return sizeof(GLuint);
2314 				case(GL_UNSIGNED_BYTE):
2315 					return sizeof(GLubyte);
2316 				}
2317 				return 0;
2318 			}
2319 
2320 			size_t _size;
2321 			const size_t _components;
2322 			bool _isvalid;
2323 			const GLenum _gltype;
2324 			const GLenum _target;
2325 
2326 			/*WARNING!!!!!!!!!!!!!!!!! In openGL INDEX BO doesn't require to be enabled/disabled so has NOT a valid tag associated.
2327 			In this case the client state tag remains not initialized and it's not meaningful */
2328 			const GLenum _clientstatetag;
2329 			/**********************************************************************************/
2330 
2331 			GLuint _bohandle;
2332 		};
2333 
2334 		//ideally this should be const. I'm not yet sure if VCGLib will allow me to declare it as constant
2335 		MESH_TYPE& _mesh;
2336 
2337 		MemoryInfo& _gpumeminfo;
2338 
2339 		/*The buffer objects used for the rendering operation. They are shared among all the views*/
2340 		std::vector<GLBufferObject*> _bo;
2341 
2342 		typedef std::map< UNIQUE_VIEW_ID_TYPE, PVData > ViewsMap;
2343 
2344 		///*_perviewreqatts contains a map of the requested atts by each single view. it's maintained for the actual rendering step*/
2345 		ViewsMap _perviewreqatts;
2346 
2347 		/*_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*/
2348 		/* 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)*/
2349 		/*             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*/
2350 		InternalRendAtts _currallocatedboatt;
2351 
2352 		bool _borendering;
2353 		size_t _perbatchprim;
2354 
2355 		/*Additional structures used for per wedge texturing modality*/
2356 		typedef std::vector< std::pair< GLuint, GLuint > > ChunkVector;
2357 		typedef std::map< short, ChunkVector > ChunkMap;
2358 
2359 		std::vector< std::pair<short, GLuint> > _texindnumtriangles;
2360 		ChunkMap  _chunkmap;
2361 
2362 		//Horrible waste of memory space...but computing the list of edges is too much expensive...we must minimize it!
2363 		std::vector<EdgeVertInd> _edge;
2364 		size_t _meshverticeswhenedgeindiceswerecomputed;
2365 		size_t _meshtriangleswhenedgeindiceswerecomputed;
2366 
2367 		//vcg::GLOptions _glopts;
2368 		vcg::Matrix44<typename MESH_TYPE::ScalarType> _tr;
2369 
2370 		bool _debugmode;
2371 		DebugInfo _loginfo;
2372 
2373 		std::vector<InternalRendAtts> _meaningfulattsperprimitive;
2374 	};
2375 }
2376 
2377 #endif
2378