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