Developer Documentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
DrawMeshT.cc
1 /*===========================================================================*\
2  * *
3  * OpenFlipper *
4  * Copyright (c) 2001-2015, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openflipper.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenFlipper. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39  * *
40 \*===========================================================================*/
41 
42 /*===========================================================================*\
43 * *
44 * $Revision$ *
45 * $LastChangedBy$ *
46 * $Date$ *
47 * *
48 \*===========================================================================*/
49 
50 #define ACG_DRAW_MESH_TCC
51 
52 //=============================================================================
53 
54 #include "DrawMesh.hh"
55 
56 #include <ACG/GL/gl.hh>
57 #include <ACG/Geometry/GPUCacheOptimizer.hh>
58 #include <ACG/GL/VertexDeclaration.hh>
59 #include <ACG/GL/ShaderCache.hh>
60 #include <cassert>
61 #include <cmath>
62 #include <vector>
63 #include <map>
64 #include <cstring>
65 #include <fstream>
66 
67 #ifdef USE_OPENMP
68 #include <omp.h>
69 #endif
70 
71 //=============================================================================
72 
73 // print a memory usage report each draw call
74 //#define DEBUG_MEM_USAGE
75 
76 
77 namespace ACG
78 {
79 
80 template <class Mesh>
81 DrawMeshT<Mesh>::DrawMeshT(Mesh& _mesh)
82 : mesh_(_mesh),
83  rebuild_(REBUILD_NONE),
84  prevNumFaces_(0), prevNumVerts_(0),
85  colorMode_(1),
86  curVBOColorMode_(1),
87  flatMode_(0), bVBOinFlatMode_(0),
88  textureMode_(1), bVBOinHalfedgeTexMode_(1),
89  halfedgeNormalMode_(0), bVBOinHalfedgeNormalMode_(0),
90  invVertexMap_(0),
91  offsetPos_(0), offsetNormal_(20), offsetTexc_(12), offsetColor_(32),
92  textureIndexPropertyName_("Not Set"),
93  perFaceTextureCoordinatePropertyName_("Not Set"),
94  updateFullVBO_(true),
95  updatePerEdgeBuffers_(1),
96  updatePerHalfedgeBuffers_(1)
97 {
98 
99  pickVertexMethod_ = 1;
100  pickVertexShader_ = 0;
101 
102  pickFaceShader_ = 0;
103  pickEdgeShader_ = 0;
104 
106 }
107 
108 template<class Mesh>
109 template<class T>
110 const void* DrawMeshT<Mesh>::testMeshPropertyTypeT( const OpenMesh::BaseProperty* _prop, unsigned int* _outSize ) const
111 {
112  if (_outSize)
113  *_outSize = 0;
114  const void* dataPtr = 0;
115 
116  // rtti - detect type of property from openmesh via dynamic_cast
117  typedef OpenMesh::PropertyT< T > Prop1;
122 
123  const Prop1* p1 = dynamic_cast<const Prop1*>(_prop);
124  const PropVec1* pv1 = dynamic_cast<const PropVec1*>(_prop);
125  const PropVec2* pv2 = dynamic_cast<const PropVec2*>(_prop);
126  const PropVec3* pv3 = dynamic_cast<const PropVec3*>(_prop);
127  const PropVec4* pv4 = dynamic_cast<const PropVec4*>(_prop);
128 
129  if (p1 || pv1)
130  {
131  if (_outSize)
132  *_outSize = 1;
133  if (p1)
134  dataPtr = p1->data();
135  else
136  dataPtr = pv1->data();
137  }
138  else if (pv2)
139  {
140  if (_outSize)
141  *_outSize = 2;
142  dataPtr = pv2->data();
143  }
144  else if (pv3)
145  {
146  if (_outSize)
147  *_outSize = 3;
148  dataPtr = pv3->data();
149  }
150  else if (pv4)
151  {
152  if (_outSize)
153  *_outSize = 4;
154  dataPtr = pv4->data();
155  }
156 
157  return dataPtr;
158 }
159 
160 
161 template<class Mesh>
162 const void* DrawMeshT<Mesh>::getMeshPropertyType( OpenMesh::BaseProperty* _prop, GLuint* _outType, unsigned int* _outSize ) const
163 {
164  const void* dataPtr = 0;
165 
166  // try float
167  dataPtr = testMeshPropertyTypeT<float>(_prop, _outSize);
168  if (dataPtr)
169  {
170  if (_outType) *_outType = GL_FLOAT;
171  return dataPtr;
172  }
173 
174  // try byte
175  dataPtr = testMeshPropertyTypeT<char>(_prop, _outSize);
176  if (dataPtr)
177  {
178  if (_outType) *_outType = GL_BYTE;
179  return dataPtr;
180  }
181 
182  // try ubyte
183  dataPtr = testMeshPropertyTypeT<unsigned char>(_prop, _outSize);
184  if (dataPtr)
185  {
186  if (_outType) *_outType = GL_UNSIGNED_BYTE;
187  return dataPtr;
188  }
189 
190  // try double
191  dataPtr = testMeshPropertyTypeT<double>(_prop, _outSize);
192 
193  if (dataPtr)
194  {
195  if (_outType) *_outType = GL_DOUBLE;
196  return dataPtr;
197  }
198 
199  // try int
200  dataPtr = testMeshPropertyTypeT<int>(_prop, _outSize);
201 
202  if (dataPtr)
203  {
204  if (_outType) *_outType = GL_INT;
205  return dataPtr;
206  }
207 
208  // try uint
209  dataPtr = testMeshPropertyTypeT<unsigned int>(_prop, _outSize);
210 
211  if (dataPtr)
212  {
213  if (_outType) *_outType = GL_UNSIGNED_INT;
214  return dataPtr;
215  }
216 
217  // try short
218  dataPtr = testMeshPropertyTypeT<short>(_prop, _outSize);
219 
220  if (dataPtr)
221  {
222  if (_outType) *_outType = GL_SHORT;
223  return dataPtr;
224  }
225 
226  // try ushort
227  dataPtr = testMeshPropertyTypeT<unsigned short>(_prop, _outSize);
228 
229  if (dataPtr)
230  {
231  if (_outType) *_outType = GL_UNSIGNED_SHORT;
232  return dataPtr;
233  }
234 
235 
236  // unknown data type
237  if (_outSize)
238  *_outSize = 0;
239 
240  if (_outType)
241  *_outType = 0;
242 
243  return 0;
244 }
245 
246 
247 
248 template<class Mesh>
250 {
251 
252 public:
253 
254  DrawMeshFaceInput(Mesh& _mesh) :
255  mesh_(_mesh)
256  {
257  };
258 
259  // map[attrID] -> use per halfedge/vertex attribute (true/false)
260  std::vector<int> attributeStoredPerHalfedge_;
261 
262 
263  int getNumFaces() const { return mesh_.n_faces(); }
264 
265  // compute number of indices later automatically
266  int getNumIndices() const { return 0; };
267 
271  int getFaceSize(const int _faceID) const
272  {
273  return mesh_.valence( mesh_.face_handle(_faceID) );
274  }
275 
283  int getSingleFaceAttr(const int _faceID, const int _faceCorner, const int _attrID) const
284  {
285  const typename Mesh::FaceHandle fh = mesh_.face_handle(_faceID);
286 
287  typename Mesh::ConstFaceHalfedgeIter fh_it = mesh_.cfh_iter(fh);
288 
289  // ========================================================================================
290  // Optimization for triangular meshes (use previous halfedge to skip part of the iteration)
291  // ========================================================================================
292  if ( mesh_.is_trimesh()) {
293  if ( attributeStoredPerHalfedge_[_attrID] != 0 ) {
294  switch (_faceCorner) {
295  case 0 : return fh_it->idx();
296  break;
297  case 1 : return (mesh_.next_halfedge_handle(*fh_it)).idx();
298  break;
299  case 2 : return (mesh_.prev_halfedge_handle(*fh_it)).idx();
300  break;
301  default : std::cerr << " Index error!" << _faceCorner << std::endl; return -1;
302  break;
303  }
304  } else {
305  switch (_faceCorner) {
306  case 0 : return mesh_.to_vertex_handle(*fh_it).idx();
307  break;
308  case 1 : return (mesh_.to_vertex_handle(mesh_.next_halfedge_handle(*fh_it))).idx();
309  break;
310  case 2 : return (mesh_.to_vertex_handle(mesh_.prev_halfedge_handle(*fh_it))).idx();
311  break;
312  default : std::cerr << " Index error!" << _faceCorner << std::endl; return -1;
313  break;
314  }
315  }
316  }
317 
318  // ========================================================================================
319  // Poly Meshes
320  // ========================================================================================
321  if ( attributeStoredPerHalfedge_[_attrID] != 0 ) {
322 
323  for (int i = 0; fh_it.is_valid() && i <= _faceCorner; ++fh_it, ++i )
324  if (i == _faceCorner)
325  return fh_it->idx();
326 
327  } else {
328 
329  for (int i = 0; fh_it.is_valid() && i <= _faceCorner; ++fh_it, ++i )
330  if (i == _faceCorner)
331  return mesh_.to_vertex_handle(*fh_it).idx();
332 
333  }
334 
335  // Not found -> return -1 as error
336  return -1;
337  }
338 
345  bool getFaceAttr(const int _faceID, const int _attrID, int* _out) const
346  {
347  const typename Mesh::FaceHandle fh = mesh_.face_handle(_faceID);
348 
349  const bool usePerHalfedge = (attributeStoredPerHalfedge_[_attrID] != 0);
350 
351  // read all vertex indices of this face
352  typename Mesh::ConstFaceHalfedgeIter hh_it = mesh_.cfh_iter(fh);
353  for (int i = 0; hh_it.is_valid(); ++hh_it, ++i )
354  {
355  _out[i] = usePerHalfedge ? hh_it->idx() : mesh_.to_vertex_handle(*hh_it).idx();
356  }
357 
358  return true;
359  }
360 
366  int* getFaceAttr(const int _faceID, const int _attrID) const
367  {
368  // cannot be implemented with OpenMesh data structure
369  return 0;
370  }
371 
372 
373 
374  int getVertexAdjCount(const int _vertexID) const
375  {
376  const typename Mesh::VertexHandle vh = mesh_.vertex_handle(_vertexID);
377 
378  int counter = 0;
379 
380  // read all vertex indices of this face
381  typename Mesh::ConstVertexFaceIter adj_it = mesh_.cvf_iter(vh);
382  for (;adj_it.is_valid(); ++adj_it)
383  ++counter;
384 
385  return counter;
386  }
387 
388  int getVertexAdjFace(const int _vertexID, const int _k) const
389  {
390  const typename Mesh::VertexHandle vh = mesh_.vertex_handle(_vertexID);
391 
392  // read all vertex indices of this face
393  typename Mesh::ConstVertexFaceIter adj_it = mesh_.cvf_iter(vh);
394  for (int i = 0; adj_it.is_valid() && i < _k; ++adj_it, ++i);
395 
396  return adj_it->idx();
397  }
398 
399 private:
400  Mesh& mesh_;
401 };
402 
403 
404 
405 template <class Mesh>
406 void
408 {
409  if (rebuild_ == REBUILD_NONE) return;
410 
411  if (!mesh_.n_vertices())
412  {
413  numVerts_ = 0;
414  numTris_ = 0;
415  return;
416  }
417 
418 
419 
420  // --------------------------------------------
421  // debug - request properties
422 /*
423  if (additionalElements_.empty() && (mesh_._get_hprop("inTangent") || mesh_._get_vprop("inTangent")))
424  {
425  // VertexProperty tmp;
426  // tmp.name_ = "inTangent";
427  // tmp.source_ = 0;
428  //
429  // additionalElements_.push_back(tmp);
430 
431 // scanVertexShaderForInput( "c:/dbg/nm_VS.tpl" );
432  scanVertexShaderForInput( "/home/tenter/dbg/nm_VS.tpl" );
433  }
434 */
435  // --------------------------------------------
436 
437  // todo: check if vertex layout has been changed and eventually force a full rebuild
438 
439 
440  // update layout declaration
441  createVertexDeclaration();
442 
443  // support for point clouds:
444  if (mesh_.n_vertices() && mesh_.n_faces() == 0)
445  {
446  if (mesh_.n_vertices() > numVerts_)
447  {
448  delete [] invVertexMap_;
449  invVertexMap_ = 0;
450  }
451  numVerts_ = mesh_.n_vertices();
452  vertices_.resize(numVerts_ * vertexDecl_->getVertexStride());
453 
454  // read all vertices
455  for (size_t i = 0; i < numVerts_; ++i)
456  readVertex(i,
457  mesh_.vertex_handle(i),
458  (typename Mesh::HalfedgeHandle)(-1),
459  (typename Mesh::FaceHandle)(-1));
460 
461  createVBO();
462  rebuild_ = REBUILD_NONE;
463  return;
464  }
465 
466  invalidateFullVBO();
467 
468 
469  unsigned int maxFaceVertCount = 0;
470  unsigned int numIndices = 0;
471  unsigned int newTriCount = countTris(&maxFaceVertCount, &numIndices);
472 
473  int bTriangleRebuild = 0; // what should be rebuild?
474  int bVertexRebuild = 0;
475 
476  if (newTriCount > numTris_)
477  {
478  // index buffer too small
479  deleteIbo();
480 
481  numTris_ = newTriCount;
482 
483  bTriangleRebuild = 1;
484  }
485 
486  if (prevNumFaces_ != mesh_.n_faces())
487  {
488  bTriangleRebuild = 1;
489  prevNumFaces_ = mesh_.n_faces();
490  }
491 
492  if (prevNumVerts_ != mesh_.n_vertices())
493  {
494  if (prevNumVerts_ < mesh_.n_vertices())
495  {
496  // resize inverse vertex map
497  delete [] invVertexMap_;
498  invVertexMap_ = new unsigned int[mesh_.n_vertices()];
499  }
500 
501  bVertexRebuild = 1;
502  bTriangleRebuild = 1; // this may have caused changes in the topology!
503  prevNumVerts_ = mesh_.n_vertices();
504  }
505 
506  // support faster update by only updating vertices (do a complete update if the textures have to be rebuild)
507  if (!bTriangleRebuild && !bVertexRebuild && (rebuild_ & REBUILD_GEOMETRY) && !(rebuild_ & REBUILD_TEXTURES))
508  {
509  // only update vertices, i.e. update values of vertices
510 
511  #ifndef WIN32
512  #ifdef USE_OPENMP
513  #pragma omp parallel for
514  #endif
515  #endif
516  for (unsigned int i = 0; i < numVerts_; ++i)
517  {
518  // just pick one face, srews up face colors here so color updates need a full rebuild
519  const typename Mesh::HalfedgeHandle hh = mapToHalfedgeHandle(i);
520  typename Mesh::VertexHandle vh(-1);
521  typename Mesh::FaceHandle fh(-1);
522 
523  if (hh.is_valid())
524  {
525  vh = mesh_.to_vertex_handle(hh);
526  fh = mesh_.face_handle(hh);
527  }
528  else
529  {
530  int f_id, c_id;
531  int posID = meshComp_->mapToOriginalVertexID(i, f_id, c_id);
532  vh = mesh_.vertex_handle(posID);
533  }
534 
535  readVertex(i, vh, hh, fh);
536  }
537 
538  createVBO();
539 
540  rebuild_ = REBUILD_NONE;
541  return;
542  }
543 
544 
545  // full rebuild:
546  delete meshComp_;
547  meshComp_ = new MeshCompiler(*vertexDecl_);
548 
549 
550  // search for convenient attribute indices
551  int attrIDNorm = -1, attrIDPos = -1, attrIDTexC = -1;
552 
553  for (int i = 0; i < (int)meshComp_->getVertexDeclaration()->getNumElements(); ++i)
554  {
555  const VertexElement* e = meshComp_->getVertexDeclaration()->getElement(i);
556 
557  switch (e->usage_)
558  {
559  case VERTEX_USAGE_POSITION: attrIDPos = i; break;
560  case VERTEX_USAGE_NORMAL: attrIDNorm = i; break;
561  case VERTEX_USAGE_TEXCOORD: attrIDTexC = i; break;
562  default: break;
563  }
564  }
565 
566 
567  // pass face data to mesh compiler
568  DrawMeshFaceInput<Mesh>* faceInput = new DrawMeshFaceInput<Mesh>(mesh_);
569  faceInput->attributeStoredPerHalfedge_.resize(meshComp_->getVertexDeclaration()->getNumElements(), 0);
570  faceInput->attributeStoredPerHalfedge_[attrIDPos] = 0;
571  faceInput->attributeStoredPerHalfedge_[attrIDNorm] = ( (halfedgeNormalMode_ && mesh_.has_halfedge_normals()) ? 1 : 0 );
572  faceInput->attributeStoredPerHalfedge_[attrIDTexC] = ( mesh_.has_halfedge_texcoords2D() ? 1 : 0);
573 
574  // index source for custom attributes
575  for (size_t i = 0; i < additionalElements_.size(); ++i)
576  {
577  const VertexProperty* prop = &additionalElements_[i];
578 
579  if (prop->declElementID_ >= 0)
580  faceInput->attributeStoredPerHalfedge_[prop->declElementID_] = (prop->source_ == PROPERTY_SOURCE_HALFEDGE) ? 1 : 0;
581  }
582 
583  meshComp_->setFaceInput(faceInput);
584 
585  // set textures
586  for (unsigned int i = 0; i < mesh_.n_faces(); ++i)
587  meshComp_->setFaceGroup(i, getTextureIDofFace(i));
588 
589  // pass vertex data to mesh compiler
590 
591 
592  // points
593  meshComp_->setVertices(mesh_.n_vertices(), mesh_.points(), 24, false, GL_DOUBLE, 3);
594 
595  // normals
596  if (halfedgeNormalMode_ && mesh_.has_halfedge_normals())
597  meshComp_->setNormals(mesh_.n_halfedges(), mesh_.property(mesh_.halfedge_normals_pph()).data(), 24, false, GL_DOUBLE, 3);
598  else if (mesh_.has_vertex_normals())
599  meshComp_->setNormals(mesh_.n_vertices(), mesh_.vertex_normals(), 24, false, GL_DOUBLE, 3);
600 
601  if (mesh_.has_halfedge_texcoords2D())
602  meshComp_->setTexCoords(mesh_.n_halfedges(), mesh_.htexcoords2D(), 8, false, GL_FLOAT, 2);
603 
604  // add more requested custom attribtues to mesh compiler here..
605 
606  for (size_t i = 0; i < additionalElements_.size(); ++i)
607  {
608  VertexProperty* propDesc = &additionalElements_[i];
609 
610  if (propDesc->declElementID_ >= 0)
611  {
612  const VertexElement* el = vertexDecl_->getElement((unsigned int)propDesc->declElementID_);
613 
615  {
616  // get openmesh property handle
617  OpenMesh::BaseProperty* baseProp = 0;
618 
619  switch (propDesc->source_)
620  {
621  case PROPERTY_SOURCE_VERTEX: baseProp = mesh_._get_vprop(propDesc->name_); break;
622  case PROPERTY_SOURCE_FACE: baseProp = mesh_._get_fprop(propDesc->name_); break;
623  case PROPERTY_SOURCE_HALFEDGE: baseProp = mesh_._get_hprop(propDesc->name_); break;
624  default: baseProp = mesh_._get_vprop(propDesc->name_); break;
625  }
626 
627  if (baseProp)
628  {
629  int numAttribs = baseProp->n_elements();
630  const void* attribData = propDesc->propDataPtr_;
631 
632  meshComp_->setAttribVec( propDesc->declElementID_, numAttribs, attribData );
633  }
634 
635 
636  }
637  }
638 
639 
640  }
641 
642 
643  // compile draw buffers
644  meshComp_->build(true, true, true, true);
645 
646 
647  // create inverse vertex map
648  for (int i = 0; i < (int)mesh_.n_faces(); ++i)
649  {
650  typename Mesh::FaceHandle fh = mesh_.face_handle(i);
651 
652  int corner = 0;
653 
654  for (typename Mesh::FaceHalfedgeIter hh_it = mesh_.fh_iter(fh); hh_it.is_valid(); ++hh_it )
655  {
656  int vertexId = mesh_.to_vertex_handle(*hh_it).idx();
657  invVertexMap_[vertexId] = meshComp_->mapToDrawVertexID(i, corner++);
658  }
659  }
660 
661 
662  // get vertex buffer
663  numTris_ = meshComp_->getNumTriangles();
664  numVerts_ = meshComp_->getNumVertices();
665 
666  vertices_.resize(numVerts_ * vertexDecl_->getVertexStride());
667  meshComp_->getVertexBuffer(&vertices_[0]);
668 
669  // copy colors
670  for (int i = 0; i < (int)numVerts_; ++i)
671  {
672  typename Mesh::HalfedgeHandle hh = mapToHalfedgeHandle(i);
673 
674  unsigned int col = 0;
675 
676  if (hh.is_valid())
677  col = getVertexColor(mesh_.to_vertex_handle(hh));
678  else
679  {
680  // isolated vertex
681  int f_id, c_id;
682  int posID = meshComp_->mapToOriginalVertexID(i, f_id, c_id);
683  col = getVertexColor( mesh_.vertex_handle(posID) );
684  }
685 
686  writeColor(i, col);
687  }
688 
689  // vbo stores per vertex colors
690  curVBOColorMode_ = 1;
691 
692  // copy face colors to provoking id
693  if (colorMode_ == 2)
694  {
695  const int provokingId = meshComp_->getProvokingVertex();
696  assert(provokingId >= 0 && provokingId < 3);
697 
698  for (int i = 0; i < (int)numTris_; ++i)
699  {
700  int idx = meshComp_->getIndex(i*3+provokingId);
701 
702  int faceId = meshComp_->mapToOriginalFaceID(i);
703  unsigned int fcolor = getFaceColor(mesh_.face_handle(faceId));
704 
705  writeColor(idx, fcolor);
706  }
707 
708 #ifdef _DEBUG
709  // debug check
710 
711  for (int i = 0; i < (int)numTris_; ++i)
712  {
713  int idx = meshComp_->getIndex(i*3+provokingId);
714 
715  int faceId = meshComp_->mapToOriginalFaceID(i);
716  unsigned int fcolor = getFaceColor(mesh_.face_handle(faceId));
717 
718  unsigned int storedColor = *(unsigned int*)(&vertices_[idx * vertexDecl_->getVertexStride() + offsetColor_]);
719 
720  if (storedColor != fcolor)
721  {
722  std::cout << "warning: possibly found provoking vertex shared by more than one face, writing report to ../../meshcomp_provoking.txt" << std::endl;
723 
724  // could also be caused by multi-threading, where one thread calls rebuild()
725  // and the other thread updates face colors between previous for-loop and debug-check
726 
727  // check for errors
728  meshComp_->dbgVerify("../../meshcomp_provoking.txt");
729 
730  break; // verify and dump report only once
731  }
732  }
733 #endif // _DEBUG
734 
735  curVBOColorMode_ = colorMode_;
736  }
737 
738 
739 
740 
742  // copy to GPU
743 
744  createVBO();
745  createIBO();
746 
747  bVBOinHalfedgeNormalMode_ = halfedgeNormalMode_;
748 
749  rebuild_ = REBUILD_NONE;
750 }
751 
752 
753 template <class Mesh>
754 void
755 DrawMeshT<Mesh>::readVertex(unsigned int _vertex,
756  const typename Mesh::VertexHandle _vh,
757  const typename Mesh::HalfedgeHandle _hh,
758  const typename Mesh::FaceHandle _fh)
759 {
760  static const typename Mesh::HalfedgeHandle invalidHEH(-1);
761  static const typename Mesh::FaceHandle invalidFH(-1);
762 
763 
764  ACG::Vec3d n(0.0, 0.0, 1.0);
765  ACG::Vec2f texc(0.0f, 0.0f);
766  unsigned int col(0);
767 
768  // read normal
769  if (halfedgeNormalMode_ == 0 && mesh_.has_vertex_normals())
770  n = mesh_.normal(_vh);
771  else if (halfedgeNormalMode_ && mesh_.has_halfedge_normals() && _hh != invalidHEH)
772  n = mesh_.normal(_hh);
773 
774  // read texcoord
775  if (mesh_.has_halfedge_texcoords2D())
776  {
777  if (_hh != invalidHEH && textureMode_ == 1)
778  texc = mesh_.texcoord2D(_hh);
779  else if (mesh_.has_vertex_texcoords2D())
780  texc = mesh_.texcoord2D(_vh);
781  }
782  else if (mesh_.has_vertex_texcoords2D())
783  texc = mesh_.texcoord2D(_vh);
784 
785  // read per face or per vertex color
786  unsigned int byteCol[2];
787  for (int col = 0; col < 2; ++col)
788  {
789  Vec4uc vecCol(255, 255, 255, 255);
790 
791  if (col == 0 && mesh_.has_vertex_colors())
792  vecCol = OpenMesh::color_cast<Vec4uc, typename Mesh::Color>(mesh_.color(_vh));
793  if (_fh != invalidFH)
794  {
795  if (col == 1 && mesh_.has_face_colors() && _fh.idx() >= 0)
796  vecCol = OpenMesh::color_cast<Vec4uc,typename Mesh::Color>(mesh_.color(_fh));
797  }
798 
799  // OpenGL color format: A8B8G8R8
800  byteCol[col] = (unsigned char)(vecCol[0]);
801  byteCol[col] |= ((unsigned char)(vecCol[1])) << 8;
802  byteCol[col] |= ((unsigned char)(vecCol[2])) << 16;
803  byteCol[col] |= ((unsigned char)(vecCol[3])) << 24;
804  //byteCol[col] |= 0xFF << 24; // if no alpha channel
805  }
806 
807  if (colorMode_ != 2)
808  col = byteCol[0]; // vertex colors
809  else
810  col = byteCol[1]; // face colors
811 
812 
813  // store vertex attributes in vbo
814  writePosition(_vertex, mesh_.point(_vh));
815  writeNormal(_vertex, n);
816  writeTexcoord(_vertex, texc);
817  writeColor(_vertex, col);
818 
819 
820  // read/write custom attributes
821 
822  for (size_t i = 0; i < additionalElements_.size(); ++i)
823  {
824  std::cout << "not implemented!" << std::endl;
825 
826 
827  }
828 
829 
830 }
831 
832 template <class Mesh>
833 unsigned int
835 {
836  static const typename Mesh::VertexHandle invalidVH(-1);
837 
838  unsigned int byteCol;
839 
840  Vec4uc vecCol(255, 255, 255, 255);
841 
842  if ( _vh != invalidVH && mesh_.has_vertex_colors() )
843  vecCol = OpenMesh::color_cast<Vec4uc, typename Mesh::Color>(mesh_.color(_vh));
844 
845  // OpenGL color format: A8B8G8R8
846  byteCol = (unsigned char)(vecCol[0]);
847  byteCol |= ((unsigned char)(vecCol[1])) << 8;
848  byteCol |= ((unsigned char)(vecCol[2])) << 16;
849  byteCol |= ((unsigned char)(vecCol[3])) << 24;
850 
851  return byteCol;
852 }
853 
854 template <class Mesh>
855 unsigned int
856 DrawMeshT<Mesh>::getFaceColor(const typename Mesh::FaceHandle _fh)
857 {
858  static const typename Mesh::FaceHandle invalidFH(-1);
859 
860  unsigned int byteCol;
861  Vec4uc vecCol(255, 255, 255, 255);
862 
863  if ( _fh != invalidFH && mesh_.has_face_colors() && _fh.idx() >= 0 )
864  vecCol = OpenMesh::color_cast<Vec4uc,typename Mesh::Color>(mesh_.color(_fh));
865 
866  // OpenGL color format: A8B8G8R8
867  byteCol = (unsigned char)(vecCol[0]);
868  byteCol |= ((unsigned char)(vecCol[1])) << 8;
869  byteCol |= ((unsigned char)(vecCol[2])) << 16;
870  byteCol |= ((unsigned char)(vecCol[3])) << 24;
871 
872  return byteCol;
873 }
874 
875 
876 template <class Mesh>
877 int
879 {
880  OpenMesh::FPropHandleT< int > textureIndexProperty;
881  if (mesh_.get_property_handle(textureIndexProperty, textureIndexPropertyName_))
882  return mesh_.property(textureIndexProperty, mesh_.face_handle(_face));
883 
884  if (mesh_.has_face_texture_index())
885  return mesh_.texture_index(mesh_.face_handle(_face));
886 
887  return 0;
888 }
889 
890 template <class Mesh>
891 int
893 {
894  return getTextureIDofFace(meshComp_->mapToOriginalFaceID(_tri));
895 }
896 
897 
898 template <class Mesh>
899 void
901 {
902  bindVbo();
903 
904  // toggle between normal source and texcoord source
905  // (per vertex, per halfedge, per face)
906 
907  if (flatMode_ && meshComp_)
908  {
909  for (unsigned int i = 0; i < numTris_; ++i)
910  {
911  int faceId = meshComp_->mapToOriginalFaceID(i);
912 
913  // get face normal
914  ACG::Vec3d n = mesh_.normal(mesh_.face_handle(faceId));
915 
916  // store face normal in last tri vertex
917 // for (unsigned int k = 0; k < 3; ++k)
918  {
919  int idx = meshComp_->getIndex(i*3 + meshComp_->getProvokingVertex());
920 // vertices_[idx].n[k] = n[k];
921  writeNormal(idx, n);
922  }
923 
924  }
925  bVBOinFlatMode_ = 1;
926  }
927  else
928  {
929  for (unsigned int i = 0; i < numVerts_; ++i)
930  {
931  typename Mesh::HalfedgeHandle hh = mapToHalfedgeHandle(i);
932 
933  // get halfedge normal
934 
935  if (hh.is_valid())
936  {
937  ACG::Vec3d n;
938  if (halfedgeNormalMode_ == 1 && mesh_.has_halfedge_normals())
939  n = mesh_.normal( hh );
940  else
941  n = mesh_.normal( mesh_.to_vertex_handle(hh) );
942 
943 // for (int k = 0; k < 3; ++k)
944 // vertices_[i].n[k] = n[k];
945  writeNormal(i, n);
946  }
947  else
948  {
949  // isolated vertex
950  int posID = i;
951 
952 
953  if (meshComp_) {
954  int f_id, c_id;
955  posID = meshComp_->mapToOriginalVertexID(i, f_id, c_id);
956  }
957 
958 // for (int k = 0; k < 3; ++k)
959 // vertices_[i].tex[k] = mesh_.normal( mesh_.vertex_handle(posID) )[k];
960  writeNormal(i, mesh_.normal( mesh_.vertex_handle(posID) ));
961  }
962  }
963 
964  bVBOinFlatMode_ = 0;
965  }
966 
967  if (textureMode_ == 0)
968  {
969  // per vertex texcoords
970  if (mesh_.has_vertex_texcoords2D())
971  {
972  for (unsigned int i = 0; i < numVerts_; ++i)
973  {
974  typename Mesh::HalfedgeHandle hh = mapToHalfedgeHandle(i);
975 
976  if (hh.is_valid())
977  {
978  // copy texcoord
979 // for (int k = 0; k < 2; ++k)
980 // vertices_[i].tex[k] = mesh_.texcoord2D( mesh_.to_vertex_handle(hh) )[k];
981 
982  writeTexcoord(i, mesh_.texcoord2D( mesh_.to_vertex_handle(hh) ) );
983  }
984  else
985  {
986  // isolated vertex
987  int posID = i;
988 
989  if (meshComp_) {
990  int f_id, c_id;
991  posID = meshComp_->mapToOriginalVertexID(i, f_id, c_id);
992  }
993 
994 // for (int k = 0; k < 2; ++k)
995 // vertices_[i].tex[k] = mesh_.texcoord2D( mesh_.vertex_handle(posID) )[k];
996 
997  writeTexcoord(i, mesh_.texcoord2D( mesh_.vertex_handle(posID) ) );
998 
999  }
1000  }
1001  }
1002 
1003  bVBOinHalfedgeTexMode_ = 0;
1004  }
1005  else
1006  {
1007  if (mesh_.has_vertex_texcoords2D() || mesh_.has_halfedge_texcoords2D())
1008  {
1009  // per halfedge texcoords
1010  for (unsigned int i = 0; i < numVerts_; ++i)
1011  {
1012  typename Mesh::HalfedgeHandle hh = mapToHalfedgeHandle(i);
1013 
1014  if (hh.is_valid())
1015  {
1016  // copy texcoord
1017  if (mesh_.has_halfedge_texcoords2D())
1018  {
1019 // for (int k = 0; k < 2; ++k)
1020 // vertices_[i].tex[k] = mesh_.texcoord2D( hh )[k];
1021 
1022  writeTexcoord(i, mesh_.texcoord2D( hh ) );
1023  }
1024 
1025  }
1026  else if (mesh_.has_vertex_texcoords2D())
1027  {
1028  // isolated vertex
1029  int posID = i;
1030 
1031 
1032  if (meshComp_) {
1033  int f_id, c_id;
1034  posID = meshComp_->mapToOriginalVertexID(i, f_id, c_id);
1035  }
1036 
1037 // for (int k = 0; k < 2; ++k)
1038 // vertices_[i].tex[k] = mesh_.texcoord2D( mesh_.vertex_handle(posID) )[k];
1039 
1040  writeTexcoord(i, mesh_.texcoord2D( mesh_.vertex_handle(posID) ) );
1041 
1042  }
1043  }
1044  }
1045 
1046  bVBOinHalfedgeTexMode_ = 1;
1047  }
1048 
1049  if (colorMode_ && colorMode_ != curVBOColorMode_)
1050  {
1051  if (colorMode_ == 1)
1052  {
1053  // use vertex colors
1054 
1055  for (int i = 0; i < (int)numVerts_; ++i)
1056  {
1057  typename Mesh::HalfedgeHandle hh = mapToHalfedgeHandle(i);
1058 
1059  unsigned int col;
1060 
1061  if (hh.is_valid())
1062  col = getVertexColor(mesh_.to_vertex_handle(hh));
1063  else
1064  {
1065  // isolated vertex
1066  int f_id, c_id;
1067  int posID = meshComp_->mapToOriginalVertexID(i, f_id, c_id);
1068  col = getVertexColor( mesh_.vertex_handle(posID) );
1069  }
1070 
1071  writeColor(i, col);
1072  }
1073  }
1074  else if (colorMode_ == 2)
1075  {
1076  // use face colors
1077 
1078  const int provokingId = meshComp_->getProvokingVertex();
1079  assert(provokingId >= 0 && provokingId < 3);
1080 
1081  for (int i = 0; i < (int)numTris_; ++i)
1082  {
1083  int idx = meshComp_->getIndex(i*3+provokingId);
1084 
1085  int faceId = meshComp_->mapToOriginalFaceID(i);
1086  unsigned int fcolor = getFaceColor(mesh_.face_handle(faceId));
1087 
1088 // vertices_[idx].col = fcolor;
1089  writeColor(idx, fcolor);
1090  }
1091  }
1092 
1093  // vbo colors updated
1094  curVBOColorMode_ = colorMode_;
1095  }
1096 
1097  fillVertexBuffer();
1098 
1099  ACG::GLState::bindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
1100 
1101  // non indexed vbo needs updating now
1102  invalidateFullVBO();
1103 }
1104 
1105 template <class Mesh>
1106 void
1108 {
1109  // data read from indices_
1110 
1111  bindIbo();
1112 
1113  indexType_ = GL_UNSIGNED_INT;
1114 // if (numVerts_ <= 0xFFFF)
1115 // {
1116 // // use 2 byte indices
1117 // unsigned short* pwIndices = (unsigned short*)indicesTmp_;
1118 // indexType_ = GL_UNSIGNED_SHORT;
1119 //
1120 // for (unsigned int i = 0; i < numTris_ * 3; ++i)
1121 // pwIndices[i] = (unsigned short)indices_[i];
1122 //
1123 // glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, numTris_ * 3 * sizeof(unsigned short), pwIndices, GL_STATIC_DRAW_ARB);
1124 // }
1125 // else
1126  createIndexBuffer();
1127 
1128 
1129  // line index buffer:
1130  if (mesh_.n_edges())
1131  {
1132  std::vector<unsigned int> lineBuffer(mesh_.n_edges() * 2);
1133 
1134  for (unsigned int i = 0; i < mesh_.n_edges(); ++i)
1135  {
1136  OpenMesh::HalfedgeHandle hh = mesh_.halfedge_handle(mesh_.edge_handle(i), 0);
1137 
1138  if (indexType_ == GL_UNSIGNED_SHORT)
1139  {
1140  // put two words in a dword
1141  unsigned int combinedIdx = invVertexMap_[mesh_.from_vertex_handle(hh).idx()] | (invVertexMap_[mesh_.to_vertex_handle(hh).idx()] << 16);
1142  lineBuffer[i] = combinedIdx;
1143  }
1144  else
1145  {
1146  lineBuffer[2 * i] = invVertexMap_[mesh_.from_vertex_handle(hh).idx()];
1147  lineBuffer[2 * i + 1] = invVertexMap_[mesh_.to_vertex_handle(hh).idx()];
1148  }
1149  }
1150 
1151  bindLineIbo();
1152 
1153  fillLineBuffer(mesh_.n_edges(), &lineBuffer[0]);
1154  }
1155 
1156  ACG::GLState::bindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
1157 }
1158 
1159 template <class Mesh>
1161 {
1162  delete [] invVertexMap_;
1163 }
1164 
1165 
1166 
1167 template <class Mesh>
1168 unsigned int DrawMeshT<Mesh>::getMemoryUsage(bool _printReport)
1169 {
1170  unsigned int res = 0;
1171  unsigned int sysBufSize = 0;
1172 
1173  sysBufSize += meshComp_->getMemoryUsage();
1174 
1175  // vertex buffer
1176  if (!vertices_.empty())
1177  sysBufSize += vertexDecl_->getVertexStride() * numVerts_;
1178 
1179 
1180 
1181  res += sysBufSize;
1182 
1183  // mappings
1184  unsigned int mapsSize = 0;
1185 
1186  if (invVertexMap_)
1187  res += mesh_.n_vertices() * 4;
1188 
1189  res += mapsSize;
1190 
1191 
1192  // picking buffers
1193  unsigned int pickBufSize = 0;
1194 
1195  pickBufSize += pickVertBuf_.capacity() * sizeof(ACG::Vec3f);
1196  pickBufSize += pickVertColBuf_.capacity() * sizeof(ACG::Vec4uc);
1197 
1198  pickBufSize += pickEdgeBuf_.capacity() * sizeof(ACG::Vec4uc);
1199 
1200  pickBufSize += pickFaceVertexBuf_.capacity() * sizeof(ACG::Vec3f);
1201  pickBufSize += pickFaceColBuf_.capacity() * sizeof(ACG::Vec4uc);
1202 
1203 
1204  pickBufSize += pickAnyFaceColBuf_.capacity() * sizeof(ACG::Vec4uc);
1205  pickBufSize += pickAnyEdgeColBuf_.capacity() * sizeof(ACG::Vec4uc);
1206  pickBufSize += pickAnyVertexColBuf_.capacity() * sizeof(ACG::Vec4uc);
1207 
1208  res += pickBufSize;
1209 
1210 
1211  // edge and halfedge vertex buffers (glDraw from sysmem)
1212  unsigned int edgeBufSize = 0;
1213 
1214  edgeBufSize += perEdgeVertexBuf_.capacity() * sizeof(ACG::Vec3f);
1215  edgeBufSize += perEdgeColorBuf_.capacity() * sizeof(ACG::Vec4uc);
1216 
1217  edgeBufSize += perHalfedgeVertexBuf_.capacity() * sizeof(ACG::Vec3f);
1218  edgeBufSize += perHalfedgeColorBuf_.capacity() * sizeof(ACG::Vec4uc);
1219 
1220 
1221  res += edgeBufSize;
1222 
1223 
1224  unsigned int gpuBufSize = 0;
1225 
1226  if (ibo_)
1227  gpuBufSize += numTris_ * 3 * (indexType_ == GL_UNSIGNED_INT ? 4 : 2);
1228 
1229  if (vbo_)
1230  gpuBufSize += numVerts_ * vertexDecl_->getVertexStride();
1231 
1232  if (_printReport)
1233  {
1234  std::cout << "\nDrawMesh memory usage in MB:\n";
1235  std::cout << "Vertex+IndexBuffer (SYSMEM only): " << float(sysBufSize) / (1024 * 1024);
1236  std::cout << "\nMappings: " << float(mapsSize) / (1024 * 1024);
1237  std::cout << "\nPicking Buffers: " << float(pickBufSize) / (1024 * 1024);
1238  std::cout << "\nEdge Buffers: " << float(edgeBufSize) / (1024 * 1024);
1239  std::cout << "\nTotal SYSMEM: " << float(res) / (1024 * 1024);
1240  std::cout << "\nTotal GPU: " << float(gpuBufSize) / (1024 * 1024) << std::endl;
1241  }
1242 
1243  return res;
1244 }
1245 
1246 
1247 template <class Mesh>
1249 {
1250  // rebuild if necessary
1251  if ((!numTris_ && mesh_.n_faces())|| ! numVerts_ || (!meshComp_ && mesh_.n_faces()))
1252  {
1253  rebuild_ = REBUILD_FULL;
1254  }
1255 
1256  if (bVBOinHalfedgeNormalMode_ != halfedgeNormalMode_) rebuild_ = REBUILD_FULL;
1257 
1258  // if no rebuild necessary, check for smooth / flat shading switch
1259  // to update normals
1260  if (rebuild_ == REBUILD_NONE)
1261  {
1262  if (bVBOinFlatMode_ != flatMode_ || bVBOinHalfedgeTexMode_ != textureMode_ || (colorMode_ && curVBOColorMode_ != colorMode_))
1263  createVBO();
1264  }
1265  else
1266  {
1267  rebuild();
1268  }
1269 }
1270 
1271 
1272 template <class Mesh>
1274 {
1275  updateGPUBuffers();
1276  return vbo_;
1277 }
1278 
1279 template <class Mesh>
1281 {
1282  updateGPUBuffers();
1283  return ibo_;
1284 }
1285 
1286 template <class Mesh>
1287 unsigned int DrawMeshT<Mesh>::mapVertexToVBOIndex(unsigned int _v)
1288 {
1289  if (_v < mesh_.n_vertices())
1290  {
1291  if (invVertexMap_)
1292  return invVertexMap_[_v];
1293  else //if mesh is a point cloud
1294  return _v;
1295  }
1296 
1297  return (unsigned int)-1;
1298 }
1299 
1300 template <class Mesh>
1302 {
1303  updateGPUBuffers();
1304 
1305  ACG::GLState::bindBuffer(GL_ARRAY_BUFFER_ARB, vbo_);
1306 
1307  // prepare color mode
1308  if (colorMode_)
1309  {
1310  ACG::GLState::colorPointer(4, GL_UNSIGNED_BYTE, vertexDecl_->getVertexStride(), (char*)offsetColor_);
1311  ACG::GLState::enableClientState(GL_COLOR_ARRAY);
1312  }
1313 
1314  // vertex decl
1315  ACG::GLState::vertexPointer(3, GL_FLOAT, vertexDecl_->getVertexStride(), (char*)offsetPos_);
1316  ACG::GLState::enableClientState(GL_VERTEX_ARRAY);
1317 
1318  glClientActiveTexture(GL_TEXTURE0);
1319  ACG::GLState::texcoordPointer(2, GL_FLOAT, vertexDecl_->getVertexStride(), (char*)offsetTexc_);
1320  ACG::GLState::enableClientState(GL_TEXTURE_COORD_ARRAY);
1321 
1322  ACG::GLState::normalPointer(GL_FLOAT, vertexDecl_->getVertexStride(), (char*)offsetNormal_);
1323  ACG::GLState::enableClientState(GL_NORMAL_ARRAY);
1324 
1325 // ACG::GLState::normalPointerEXT(3, GL_FLOAT, sizeof(Vertex), (char*)(20)); // ACG::GLState::normalPointerEXT crashes sth. in OpenGL
1326 
1327  ACG::GLState::bindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, ibo_);
1328 }
1329 
1330 template <class Mesh>
1332 {
1333  updateGPUBuffers();
1334 
1335  _obj->vertexBuffer = vbo_;
1336  _obj->indexBuffer = ibo_;
1337 
1338  _obj->indexType = indexType_;
1339 
1340  // assign correct vertex declaration
1341  _obj->vertexDecl = vertexDecl_;
1342 }
1343 
1344 template <class Mesh>
1346 {
1347  ACG::GLState::disableClientState(GL_VERTEX_ARRAY);
1348  ACG::GLState::disableClientState(GL_TEXTURE_COORD_ARRAY);
1349  ACG::GLState::disableClientState(GL_NORMAL_ARRAY);
1350 
1351  if (colorMode_)
1352  ACG::GLState::disableClientState(GL_COLOR_ARRAY);
1353 
1354  ACG::GLState::bindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
1355  ACG::GLState::bindBuffer(GL_ARRAY_BUFFER_ARB, 0);
1356 }
1357 
1358 template <class Mesh>
1359 void DrawMeshT<Mesh>::draw(std::map< int, GLuint>* _textureMap, bool _nonindexed)
1360 {
1361  if (!_nonindexed)
1362  bindBuffers();
1363  else
1364  {
1365  updateFullVBO();
1366  vboFull_.bind();
1367  vertexDecl_->activateFixedFunction();
1368  }
1369 
1370 #ifdef DEBUG_MEM_USAGE
1371  getMemoryUsage(true);
1372 #endif
1373 
1374  if (numTris_)
1375  {
1376  if (_textureMap)
1377  {
1378  // textured mode
1379 
1380  for (int i = 0; i < meshComp_->getNumSubsets(); ++i)
1381  {
1382  const MeshCompiler::Subset* sub = meshComp_->getSubset(i);
1383 
1384  if ( _textureMap->find(sub->id) == _textureMap->end() ) {
1385  std::cerr << "Illegal texture index ... trying to access " << sub->id << std::endl;
1386  ACG::GLState::bindTexture(GL_TEXTURE_2D, 0);
1387  }
1388  else
1389  ACG::GLState::bindTexture(GL_TEXTURE_2D, (*_textureMap)[sub->id]);
1390 
1391  if (!_nonindexed)
1392  glDrawElements(GL_TRIANGLES, sub->numTris * 3, indexType_,
1393  (GLvoid*)( (size_t)sub->startIndex * (indexType_ == GL_UNSIGNED_INT ? 4 : 2))); // offset in bytes
1394  else
1395  glDrawArrays(GL_TRIANGLES, sub->startIndex, sub->numTris * 3);
1396  }
1397  }
1398  else
1399  {
1400  if (!_nonindexed)
1401  glDrawElements(GL_TRIANGLES, numTris_ * 3, indexType_, 0);
1402  else
1403  glDrawArrays(GL_TRIANGLES, 0, numTris_ * 3);
1404  }
1405  }
1406 
1407  unbindBuffers();
1408 }
1409 
1410 
1411 template <class Mesh>
1412 void ACG::DrawMeshT<Mesh>::addTriRenderObjects(IRenderer* _renderer, const RenderObject* _baseObj, std::map< int, GLuint>* _textureMap, bool _nonindexed)
1413 {
1414  if (numTris_)
1415  {
1416  RenderObject ro = *_baseObj;
1417  if (!_nonindexed)
1418  bindBuffersToRenderObject(&ro);
1419  else
1420  {
1421  updateFullVBO();
1422 
1423  ro.vertexBuffer = vboFull_.id();
1424  ro.vertexDecl = vertexDecl_;
1425  }
1426 
1427  if (_baseObj->shaderDesc.textured())
1428  {
1429  // textured mode
1430 
1431  for (int i = 0; i < meshComp_->getNumSubsets(); ++i)
1432  {
1433  const MeshCompiler::Subset* sub = meshComp_->getSubset(i);
1434 
1435  if ( _textureMap )
1436  {
1437  if ( _textureMap->find(sub->id) == _textureMap->end() ) {
1438  std::cerr << "Illegal texture index ... trying to access " << sub->id << std::endl;
1439  }
1440  else
1441  {
1443  tex.type = GL_TEXTURE_2D;
1444  tex.id = (*_textureMap)[sub->id];
1445  ro.addTexture(tex,0);
1446  }
1447  }
1448  else // no texture map specified, use whatever texture is currently bound to the first texture stage
1449  {
1450  glActiveTextureARB(GL_TEXTURE0);
1451  GLint textureID = 0;
1452  glGetIntegerv(GL_TEXTURE_BINDING_2D, &textureID);
1453 
1455  tex.type = GL_TEXTURE_2D;
1456  tex.id = textureID;
1457  ro.addTexture(tex,0);
1458  }
1459 
1460 
1461 
1462  if (!_nonindexed)
1463  ro.glDrawElements(GL_TRIANGLES, sub->numTris * 3, indexType_,
1464  (GLvoid*)((size_t)sub->startIndex * (indexType_ == GL_UNSIGNED_INT ? 4 : 2))); // offset in bytes
1465  else
1466  ro.glDrawArrays(GL_TRIANGLES, sub->startIndex, sub->numTris * 3);
1467 
1468  _renderer->addRenderObject(&ro);
1469  }
1470  }
1471  else
1472  {
1473  if (!_nonindexed)
1474  ro.glDrawElements(GL_TRIANGLES, numTris_ * 3, indexType_, 0);
1475  else
1476  ro.glDrawArrays(GL_TRIANGLES,0, numTris_ * 3);
1477  _renderer->addRenderObject(&ro);
1478  }
1479  }
1480 }
1481 
1482 
1483 template <class Mesh>
1485 {
1486  bindBuffers();
1487 
1488  if (mesh_.n_edges())
1489  {
1490  ACG::GLState::bindBuffer(GL_ELEMENT_ARRAY_BUFFER, lineIBO_);
1491 
1492  glDrawElements(GL_LINES, mesh_.n_edges() * 2, indexType_, 0);
1493  }
1494 
1495  unbindBuffers();
1496 }
1497 
1498 
1499 template <class Mesh>
1501 {
1502  RenderObject ro = *_baseObj;
1503  bindBuffersToRenderObject(&ro);
1504 
1505  if (mesh_.n_edges())
1506  {
1507  ro.indexBuffer = lineIBO_;
1508  ro.glDrawElements(GL_LINES, mesh_.n_edges() * 2, indexType_, 0);
1509 
1510  _renderer->addRenderObject(&ro);
1511  }
1512 }
1513 
1514 template <class Mesh>
1516 {
1517 
1518  bindBuffers();
1519 
1520  if (numVerts_)
1521  glDrawArrays(GL_POINTS, 0, numVerts_);
1522 
1523  unbindBuffers();
1524 }
1525 
1526 template <class Mesh>
1528 {
1529  RenderObject ro = *_baseObj;
1530  bindBuffersToRenderObject(&ro);
1531 
1532  if (numVerts_)
1533  {
1534  ro.glDrawArrays(GL_POINTS, 0, numVerts_);
1535 
1536  _renderer->addRenderObject(&ro);
1537  }
1538 }
1539 
1541 
1542 template <class Mesh>
1543 unsigned int DrawMeshT<Mesh>::countTris(unsigned int* pMaxVertsOut, unsigned int* _pOutNumIndices)
1544 {
1545  unsigned int triCounter = 0;
1546 
1547  if (pMaxVertsOut) *pMaxVertsOut = 0;
1548  if (_pOutNumIndices) *_pOutNumIndices = 0;
1549 
1550  for (unsigned int i = 0; i < mesh_.n_faces(); ++i)
1551  {
1552  typename Mesh::FaceHandle fh = mesh_.face_handle(i);
1553 
1554  // count vertices
1555  unsigned int nPolyVerts = 0;
1556 
1557  for (typename Mesh::FaceHalfedgeIter hh_it = mesh_.fh_iter(fh); hh_it.is_valid(); ++hh_it ) ++nPolyVerts;
1558 
1559  triCounter += (nPolyVerts - 2);
1560 
1561  if (pMaxVertsOut)
1562  {
1563  if (*pMaxVertsOut < nPolyVerts)
1564  *pMaxVertsOut = nPolyVerts;
1565  }
1566 
1567  if (_pOutNumIndices) *_pOutNumIndices += nPolyVerts;
1568  }
1569 
1570  return triCounter;
1571 }
1572 
1573 
1574 
1575 template <class Mesh>
1577 {
1578  // Force update of the buffers if required
1579  if (updatePerEdgeBuffers_)
1580  updatePerEdgeBuffers();
1581  return perEdgeVertexBuf_.empty() ? 0 : &(perEdgeVertexBuf_[0]);
1582 }
1583 
1584 template <class Mesh>
1586 {
1587  // Force update of the buffers if required
1588  if (updatePerEdgeBuffers_)
1589  updatePerEdgeBuffers();
1590  return perEdgeColorBuf_.empty() ? 0 : &(perEdgeColorBuf_[0]);
1591 }
1592 
1593 
1594 template <class Mesh>
1596  uint _offset)
1597 {
1598  unsigned int idx = 0;
1599 
1600  // Adjust size of the color buffer to the number of vertices in the mesh
1601  pickVertColBuf_.resize( mesh_.n_vertices() );
1602  pickVertBuf_.resize( mesh_.n_vertices() );
1603 
1604  // Get the right picking colors from the gl state and add them per vertex to the color buffer
1605  typename Mesh::ConstVertexIter v_it(mesh_.vertices_begin()), v_end(mesh_.vertices_end());
1606  for (; v_it!=v_end; ++v_it, ++idx)
1607  {
1608  pickVertColBuf_[idx] = _state.pick_get_name_color(idx + _offset);
1609  pickVertBuf_[idx] = mesh_.point(mesh_.vertex_handle(idx));
1610  }
1611 }
1612 
1613 
1614 template <class Mesh>
1616 {
1617  // Make sure, the face buffers are up to date before generating the picking data!
1618  if (!numVerts_ && mesh_.n_vertices())
1619  {
1620  rebuild_ = REBUILD_FULL;
1621  rebuild();
1622  }
1623 
1624 #ifndef GL_ARB_texture_buffer_object
1625  pickVertexMethod_ = 1; // no texture buffers supported during compilation
1626 #endif
1627 
1628  if (numVerts_)
1629  {
1630  // upload vbo id->openmesh id lookup-table to texture buffer
1631 
1632  if (pickVertexMethod_ == 0)
1633  {
1634 #ifdef GL_ARB_texture_buffer_object
1635 
1636  std::vector<int> forwardMap(numVerts_, 0);
1637 
1638  for (int i = 0; i < (int)numVerts_; ++i)
1639  {
1640  int vboIdx = mapVertexToVBOIndex(i);
1641  if (vboIdx >= 0)
1642  forwardMap[vboIdx] = i;
1643  }
1644  pickVertexMapTBO_.setBufferData(sizeof(int) * numVerts_, &forwardMap[0], GL_R32I, GL_STATIC_DRAW);
1645 
1646 #endif // GL_ARB_texture_buffer_object
1647 
1648  }
1649  else
1650  {
1651  // Another method: draw with index buffer, which contains the mapping from openmesh vertex id to drawmesh vbo vertex.
1652  // problem with this: gl_VertexID is affected by index buffer and thus represents the drawmesh vbo ids
1653  // -> use gl_PrimitiveID instead, which represents the openmesh vertex id
1654  if (invVertexMap_)
1655  {
1656  bindPickVertexIbo();
1657  fillInvVertexMap(mesh_.n_vertices(), invVertexMap_);
1658  ACG::GLState::bindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
1659  }
1660 
1661  }
1662  }
1663 }
1664 
1665 
1666 template <class Mesh>
1668 {
1669  // load and compile picking shader
1670 
1671  // load once directly from files:
1672 // if (!pickVertexShader_)
1673 // {
1674 // if (pickVertexMethod_ == 0)
1675 // pickVertexShader_ = GLSL::loadProgram("Picking/pick_vertices_vs.glsl", "Picking/pick_vertices_fs.glsl");
1676 // else
1677 // pickVertexShader_ = GLSL::loadProgram("Picking/vertex.glsl", "Picking/pick_vertices_fs2.glsl");
1678 // }
1679 
1680  // load from cache
1681  if (pickVertexMethod_ == 0)
1682  pickVertexShader_ = ShaderCache::getInstance()->getProgram("Picking/pick_vertices_vs.glsl", "Picking/pick_vertices_fs.glsl", 0, false);
1683  else
1684  pickVertexShader_ = ShaderCache::getInstance()->getProgram("Picking/vertex.glsl", "Picking/pick_vertices_fs2.glsl", 0, false);
1685 
1686  // check link status
1687  return pickVertexShader_ && pickVertexShader_->isLinked();
1688 }
1689 
1690 
1691 template <class Mesh>
1692 void ACG::DrawMeshT<Mesh>::drawPickingVertices_opt( const GLMatrixf& _mvp, int _pickOffset )
1693 {
1694  // optimized version which computes picking ids in the shader
1695 
1696  /*
1697  pickVertexMethod_
1698  0: - create a textureBuffer containing the mapping from vbo id to openmesh vertex id
1699  - draw point list of the main vbo and read texture map in the vertex shader
1700  - computation in vertex shader via gl_VertexID
1701  -> required mem: 4 bytes per vertex in draw vbo
1702  -> # vertex transforms: vertex count in draw vbo
1703 
1704  1: - create index buffer containing the mapping from openmesh vertex id to vbo id
1705  (not required for point-clouds)
1706  - draw point list with index buffer
1707  - computation in fragment shader via gl_PrimitiveID
1708  -> required mem: nothing for point-clouds, otherwise 4 bytes per vertex in openmesh
1709  -> # vertex transforms: vertex count in openmesh
1710 
1711  method 1 is probably more efficient overall
1712  */
1713 
1714  // test support by loading and compiling picking shader
1715  if (!supportsPickingVertices_opt())
1716  return;
1717 
1718  ACG::GLState::bindBufferARB(GL_ARRAY_BUFFER_ARB, getVBO());
1719 
1720  if (pickVertexMethod_ == 1 && invVertexMap_)
1721  bindPickVertexIbo();
1722 
1723  // setup picking shader
1724  pickVertexShader_->use();
1725  getVertexDeclaration()->activateShaderPipeline(pickVertexShader_);
1726 
1727  pickVertexShader_->setUniform("pickVertexOffset", _pickOffset);
1728 
1729  if (pickVertexMethod_ == 0)
1730  {
1731  pickVertexShader_->setUniform("vboToInputMap", 0);
1732 #ifdef GL_ARB_texture_buffer_object
1733  pickVertexMap_opt()->bind(GL_TEXTURE0);
1734 #endif
1735  }
1736 
1737  pickVertexShader_->setUniform("mWVP", _mvp);
1738 
1739  // draw call
1740  if (pickVertexMethod_ == 0)
1741  glDrawArrays(GL_POINTS, 0, getNumVerts());
1742  else
1743  {
1744  if (pickVertexIBO_opt() && invVertexMap_)
1745  glDrawElements(GL_POINTS, mesh_.n_vertices(), GL_UNSIGNED_INT, 0);
1746  else
1747  glDrawArrays(GL_POINTS, 0, mesh_.n_vertices());
1748  }
1749 
1750  // restore gl state
1751  getVertexDeclaration()->deactivateShaderPipeline(pickVertexShader_);
1752  pickVertexShader_->disable();
1753 
1754  // unbind draw buffers
1755  ACG::GLState::bindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
1756 
1757  if (pickVertexMethod_ == 1)
1758  ACG::GLState::bindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
1759 }
1760 
1761 
1762 
1763 template <class Mesh>
1765 {
1766  // Only update buffers if they are invalid
1767  if (!updatePerEdgeBuffers_)
1768  return;
1769 
1770  perEdgeVertexBuf_.resize(mesh_.n_edges() * 2);
1771 
1772  if ( mesh_.has_edge_colors() ) {
1773  perEdgeColorBuf_.resize(mesh_.n_edges() * 2);
1774  } else
1775  perEdgeColorBuf_.clear();
1776 
1777  unsigned int idx = 0;
1778 
1779  typename Mesh::ConstEdgeIter e_it(mesh_.edges_sbegin()), e_end(mesh_.edges_end());
1780  for (; e_it!=e_end; ++e_it) {
1781 
1782  perEdgeVertexBuf_[idx] = mesh_.point(mesh_.to_vertex_handle(mesh_.halfedge_handle(*e_it, 0)));
1783  perEdgeVertexBuf_[idx+1] = mesh_.point(mesh_.to_vertex_handle(mesh_.halfedge_handle(*e_it, 1)));
1784 
1785  if ( mesh_.has_edge_colors() ) {
1786  const Vec4f color = OpenMesh::color_cast<Vec4f>( mesh_.color(*e_it) ) ;
1787  perEdgeColorBuf_[ idx ] = color;
1788  perEdgeColorBuf_[ idx + 1 ] = color;
1789  }
1790 
1791  idx += 2;
1792  }
1793 
1794 
1795  updatePerEdgeBuffers_ = 0;
1796 
1797  updateEdgeHalfedgeVertexDeclarations();
1798 }
1799 
1800 template <class Mesh>
1801 template<typename Mesh::Normal (DrawMeshT<Mesh>::*NormalLookup)(typename Mesh::FaceHandle)>
1803 {
1804  // Only update buffers if they are invalid
1805  if (!updatePerHalfedgeBuffers_)
1806  return;
1807 
1808  perHalfedgeVertexBuf_.resize(mesh_.n_halfedges() * 2);
1809 
1810  if ( mesh_.has_halfedge_colors() ) {
1811  perHalfedgeColorBuf_.resize(mesh_.n_halfedges() * 2);
1812  } else
1813  perHalfedgeColorBuf_.clear();
1814 
1815  unsigned int idx = 0;
1816 
1817  for (typename Mesh::ConstHalfedgeIter he_it(mesh_.halfedges_sbegin()), he_end(mesh_.halfedges_end());
1818  he_it != he_end; ++he_it) {
1819 
1820  typename Mesh::HalfedgeHandle next_heh = mesh_.next_halfedge_handle(*he_it);
1821  typename Mesh::HalfedgeHandle previous_heh = mesh_.prev_halfedge_handle(*he_it);
1822 
1823  if (mesh_.is_valid_handle(next_heh) && mesh_.is_valid_handle(previous_heh))
1824  {
1825  perHalfedgeVertexBuf_[idx] = halfedge_point<NormalLookup>(*he_it);
1826  perHalfedgeVertexBuf_[idx+1] = halfedge_point<NormalLookup>(previous_heh);
1827  }
1828  else
1829  {
1830  // Cannot compute shifted vertex positions. Use original vertex positions instead.
1831  perHalfedgeVertexBuf_[idx ] = mesh_.point(mesh_.to_vertex_handle(*he_it));
1832  perHalfedgeVertexBuf_[idx+1] = mesh_.point(mesh_.from_vertex_handle(*he_it));
1833  }
1834 
1835  if ( mesh_.has_halfedge_colors() ) {
1836  const Vec4f color = OpenMesh::color_cast<Vec4f>( mesh_.color(*he_it) ) ;
1837  perHalfedgeColorBuf_[ idx ] = color;
1838  perHalfedgeColorBuf_[ idx + 1 ] = color;
1839  }
1840 
1841  idx += 2;
1842  }
1843 
1844  updatePerHalfedgeBuffers_ = 0;
1845 
1846  updateEdgeHalfedgeVertexDeclarations();
1847 }
1848 
1849 template<class Mesh>
1850 template<typename Mesh::Normal (DrawMeshT<Mesh>::*NormalLookup)(typename Mesh::FaceHandle)>
1851 typename Mesh::Point DrawMeshT<Mesh>::halfedge_point(const typename Mesh::HalfedgeHandle _heh) {
1852 
1853  typename Mesh::Point p = mesh_.point(mesh_.to_vertex_handle (_heh));
1854  typename Mesh::Point pp = mesh_.point(mesh_.from_vertex_handle(_heh));
1855  typename Mesh::Point pn = mesh_.point(mesh_.to_vertex_handle(mesh_.next_halfedge_handle(_heh)));
1856 
1857  // typename Mesh::Point n = (p-pp)%(pn-p);
1858  typename Mesh::Point fn;
1859  if( !mesh_.is_boundary(_heh))
1860  //fn = mesh_.normal(mesh_.face_handle(_heh));
1861  fn = (this->*NormalLookup)(mesh_.face_handle(_heh));
1862  else
1863  //fn = mesh_.normal(mesh_.face_handle(mesh_.opposite_halfedge_handle(_heh)));
1864  fn = (this->*NormalLookup)(mesh_.face_handle(mesh_.opposite_halfedge_handle(_heh)));
1865 
1866  typename Mesh::Point upd = ((fn%(pn-p)).normalize() + (fn%(p-pp)).normalize()).normalize();
1867 
1868  upd *= ((pn-p).norm()+(p-pp).norm())*0.08;
1869 
1870  return (p+upd);
1871 
1872  // double alpha = 0.1;
1873  // // correct weighting for concave triangles (or at concave boundaries)
1874  // if( (fn | n) < 0.0) alpha *=-1.0;
1875 
1876  // return (p*(1.0-2.0*alpha) + pp*alpha + pn*alpha);
1877 }
1878 
1879 template <class Mesh>
1881 {
1882  // Force update of the buffers if required
1883  if (updatePerHalfedgeBuffers_) {
1884  if (mesh_.has_face_normals())
1885  updatePerHalfedgeBuffers<&DrawMeshT::cachedNormalLookup>();
1886  else if (mesh_.is_trimesh())
1887  updatePerHalfedgeBuffers<&DrawMeshT::computedTriMeshNormal>();
1888  else
1889  updatePerHalfedgeBuffers<&DrawMeshT::computedNormal>();
1890  }
1891  return perHalfedgeVertexBuf_.empty() ? 0 : &(perHalfedgeVertexBuf_[0]);
1892 }
1893 
1894 template <class Mesh>
1896 {
1897  // Force update of the buffers if required
1898  if (updatePerHalfedgeBuffers_) {
1899  if (mesh_.has_face_normals())
1900  updatePerHalfedgeBuffers<&DrawMeshT::cachedNormalLookup>();
1901  else if (mesh_.is_trimesh())
1902  updatePerHalfedgeBuffers<&DrawMeshT::computedTriMeshNormal>();
1903  else
1904  updatePerHalfedgeBuffers<&DrawMeshT::computedNormal>();
1905  }
1906  return perHalfedgeColorBuf_.empty() ? 0 : &(perHalfedgeColorBuf_[0]);
1907 }
1908 
1909 
1910 
1911 
1912 template <class Mesh>
1914  unsigned int _offset)
1915 {
1916  updatePerEdgeBuffers();
1917 
1918  pickEdgeBuf_.resize(mesh_.n_edges() * 2);
1919 
1920 
1921  int idx = 0;
1922 
1923  typename Mesh::ConstEdgeIter e_it(mesh_.edges_sbegin()), e_end(mesh_.edges_end());
1924  for (; e_it!=e_end; ++e_it) {
1925 
1926  const Vec4uc pickColor = _state.pick_get_name_color (e_it->idx() + _offset);
1927 
1928  pickEdgeBuf_[idx] = pickColor;
1929  pickEdgeBuf_[idx+1] = pickColor;
1930 
1931  idx += 2;
1932  }
1933 }
1934 
1935 
1936 
1937 template <class Mesh>
1939 {
1940  // Make sure, the face buffers are up to date before generating the picking data!
1941  if (!numTris_ && mesh_.n_faces())
1942  {
1943  rebuild_ = REBUILD_FULL;
1944  rebuild();
1945  }
1946 
1947  // nothing else to do, optimized edge picking method has no memory overhead
1948 }
1949 
1950 
1951 template <class Mesh>
1953 {
1954  // fetch picking shader from cache (edge picking uses same shader as vertex picking)
1955  pickEdgeShader_ = ShaderCache::getInstance()->getProgram("Picking/vertex.glsl", "Picking/pick_vertices_fs2.glsl", 0, false);
1956 
1957  // check link status
1958  return pickEdgeShader_ && pickEdgeShader_->isLinked();
1959 }
1960 
1961 
1962 template <class Mesh>
1963 void ACG::DrawMeshT<Mesh>::drawPickingEdges_opt( const GLMatrixf& _mvp, int _pickOffset )
1964 {
1965  // optimized version which computes picking ids in the shader
1966 
1967  /* optimization :
1968  - reuse draw vbo of drawmesh and line index buffer (which is used for wireframe mode)
1969  the line index buffer stores all edges in the same order as they appear in openmesh
1970  - use edge id of openmesh as gl_PrimitiveID in fragment shader to compute the picking id
1971 
1972  -> no rendering from sysmem buffers
1973  -> no maintenance/update of picking colors required
1974  -> no additional memory allocation
1975  */
1976 
1977  if (!numTris_)
1978  return;
1979 
1980  // test support by loading and compiling picking shader
1981  if (!supportsPickingEdges_opt())
1982  return;
1983 
1984  ACG::GLState::bindBufferARB(GL_ARRAY_BUFFER_ARB, getVBO());
1985  bindLineIbo();
1986 
1987  // setup picking shader (same shader as in vertex picking)
1988  pickEdgeShader_->use();
1989  getVertexDeclaration()->activateShaderPipeline(pickEdgeShader_);
1990 
1991  pickEdgeShader_->setUniform("pickVertexOffset", _pickOffset);
1992  pickEdgeShader_->setUniform("mWVP", _mvp);
1993 
1994  // draw call
1995  glDrawElements(GL_LINES, mesh_.n_edges() * 2, indexType_, 0);
1996 
1997  // restore gl state
1998  getVertexDeclaration()->deactivateShaderPipeline(pickEdgeShader_);
1999  pickEdgeShader_->disable();
2000 
2001  // unbind draw buffers
2002  ACG::GLState::bindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
2003  ACG::GLState::bindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
2004 }
2005 
2006 
2007 
2008 
2009 
2010 
2011 
2012 
2013 template <class Mesh>
2015 {
2016  // Make sure, the face buffers are up to date before generating the picking data!
2017  if (!numTris_ && mesh_.n_faces())
2018  {
2019  rebuild_ = REBUILD_FULL;
2020  rebuild();
2021  }
2022 
2023  pickFaceVertexBuf_.resize(3 * numTris_);
2024  pickFaceColBuf_.resize(3 * numTris_);
2025 
2026  for (unsigned int i = 0; i < numTris_; ++i)
2027  {
2028  unsigned int faceId = (unsigned int)meshComp_->mapToOriginalFaceID((int)i);
2029 
2030  const Vec4uc pickColor = _state.pick_get_name_color ( faceId );
2031  for (unsigned int k = 0; k < 3; ++k)
2032  {
2033  int idx = meshComp_->getIndex(i*3 + k);
2034 
2035  typename Mesh::HalfedgeHandle hh = mapToHalfedgeHandle(idx);
2036  typename Mesh::VertexHandle vh;
2037 
2038  if (hh.is_valid())
2039  vh = mesh_.to_vertex_handle( hh );
2040  else
2041  {
2042  int f_id, c_id;
2043  int posID = meshComp_->mapToOriginalVertexID(idx, f_id, c_id);
2044  vh = mesh_.vertex_handle(posID);
2045  }
2046 
2047  pickFaceVertexBuf_[i * 3 + k] = mesh_.point( vh );
2048 
2049  pickFaceColBuf_[i * 3 + k] = pickColor;
2050  }
2051  }
2052 
2053 
2054 }
2055 
2056 
2057 
2058 template <class Mesh>
2060 {
2061  // Make sure, the face buffers are up to date before generating the picking data!
2062  if (!numTris_ && mesh_.n_faces())
2063  {
2064  rebuild_ = REBUILD_FULL;
2065  rebuild();
2066  }
2067 
2068 #ifdef GL_ARB_texture_buffer_object
2069  if (meshComp_ && meshComp_->getNumTriangles())
2070  {
2071  // upload tri->face lookup-table to texture buffer
2072  pickFaceTriToFaceMapTBO_.setBufferData(sizeof(int) * meshComp_->getNumTriangles(), meshComp_->mapToOriginalFaceIDPtr(), GL_R32I, GL_STATIC_DRAW);
2073  }
2074 #endif // GL_ARB_texture_buffer_object
2075 
2076 }
2077 
2078 
2079 template <class Mesh>
2081 {
2082  if (!ACG::Texture::supportsTextureBuffer())
2083  return false;
2084 
2085  // fetch picking shader from cache
2086  pickFaceShader_ = ShaderCache::getInstance()->getProgram("Picking/vertex.glsl", "Picking/pick_face.glsl", 0, false);
2087 
2088  // check link status
2089  return pickFaceShader_ && pickFaceShader_->isLinked();
2090 }
2091 
2092 
2093 template <class Mesh>
2094 void ACG::DrawMeshT<Mesh>::drawPickingFaces_opt( const GLMatrixf& _mvp, int _pickOffset )
2095 {
2096  // optimized version which computes picking ids in the shader
2097 
2098  /* optimization idea:
2099  - reuse draw buffers of drawmesh
2100  - create lookup table which maps from draw triangle id to openmesh face id (stored in textureBuffer)
2101  - get base offset of face picking: pickFaceOffset = _state.pick_get_name_color(0)
2102  - render with following fragment shader, which computes face picking ids on the fly:
2103 
2104  uniform int pickFaceOffset;
2105  uniform isamplerBuffer triangleToFaceMap;
2106 
2107  out int outPickID; // if possible to write integer. otherwise, convert to ubyte4 or sth.
2108 
2109  void main()
2110  {
2111  // map from triangle id to face id
2112  int faceID = texelFetch(triangleToFaceMap, gl_PrimitiveID);
2113 
2114  outPickID = pickFaceOffset + faceID;
2115  // maybe the integer id has to be converted to a vec4 color here, not sure
2116  }
2117 
2118  -> no rendering from sysmem buffers
2119  -> no maintenance/update of picking colors required
2120  -> lower memory footprint: 4 bytes per triangle
2121 
2122  keep old approach to stay compatible on systems which do not support texture buffers or integer arithmetic in shaders
2123  */
2124 
2125  if (!numTris_)
2126  return;
2127 
2128  // test support by loading and compiling picking shader
2129  if (!supportsPickingFaces_opt())
2130  return;
2131 
2132  // reuse cache optimized draw buffers
2133  ACG::GLState::bindBufferARB(GL_ARRAY_BUFFER_ARB, getVBO());
2134  ACG::GLState::bindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, getIBO());
2135 
2136  // setup picking shader
2137  pickFaceShader_->use();
2138  getVertexDeclaration()->activateShaderPipeline(pickFaceShader_);
2139 
2140  pickFaceShader_->setUniform("pickFaceOffset", _pickOffset);
2141  pickFaceShader_->setUniform("triToFaceMap", 0);
2142 
2143 #ifdef GL_ARB_texture_buffer_object
2144  pickFaceTriangleMap_opt()->bind(GL_TEXTURE0);
2145 #endif
2146 
2147  pickFaceShader_->setUniform("mWVP", _mvp);
2148 
2149  // draw call
2150  glDrawElements(GL_TRIANGLES, getNumTris() * 3, getIndexType(), 0);
2151 
2152  // restore gl state
2153  getVertexDeclaration()->deactivateShaderPipeline(pickFaceShader_);
2154  pickFaceShader_->disable();
2155 
2156  // unbind draw buffers
2157  ACG::GLState::bindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
2158  ACG::GLState::bindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
2159 }
2160 
2161 
2162 
2163 
2164 template <class Mesh>
2166 {
2167  if (!numTris_ && mesh_.n_faces())
2168  {
2169  rebuild_ = REBUILD_FULL;
2170  rebuild();
2171  }
2172 
2173  pickFaceVertexBuf_.resize(3 * numTris_);
2174  pickAnyFaceColBuf_.resize(3 * numTris_);
2175 
2176  for (unsigned int i = 0; i < numTris_; ++i)
2177  {
2178  int faceId = meshComp_->mapToOriginalFaceID(i);
2179  const Vec4uc pickColor = _state.pick_get_name_color ( faceId );
2180  for (unsigned int k = 0; k < 3; ++k)
2181  {
2182  int idx = meshComp_->getIndex(i*3 + k);
2183 
2184 
2185  typename Mesh::HalfedgeHandle hh = mapToHalfedgeHandle(idx);
2186  typename Mesh::VertexHandle vh;
2187 
2188  if (hh.is_valid())
2189  vh = mesh_.to_vertex_handle( hh );
2190  else
2191  {
2192  int f_id, c_id;
2193  int posID = meshComp_->mapToOriginalVertexID(idx, f_id, c_id);
2194  vh = mesh_.vertex_handle(posID);
2195  }
2196 
2197  pickFaceVertexBuf_[i * 3 + k] = mesh_.point( vh );
2198 
2199  pickAnyFaceColBuf_[i * 3 + k] = pickColor;
2200  }
2201  }
2202 
2203 
2204 
2205  updatePerEdgeBuffers();
2206 
2207  pickAnyEdgeColBuf_.resize(mesh_.n_edges() * 2);
2208 
2209  unsigned int idx = 0;
2210  typename Mesh::ConstEdgeIter e_it(mesh_.edges_sbegin()), e_end(mesh_.edges_end());
2211  for (; e_it!=e_end; ++e_it) {
2212 
2213  const Vec4uc pickColor = _state.pick_get_name_color (e_it->idx() + mesh_.n_faces());
2214 
2215  pickAnyEdgeColBuf_[idx] = pickColor;
2216  pickAnyEdgeColBuf_[idx+1] = pickColor;
2217 
2218  idx += 2;
2219  }
2220 
2221 
2222 
2223  idx = 0;
2224 
2225  // Adjust size of the color buffer to the number of vertices in the mesh
2226  pickAnyVertexColBuf_.resize( mesh_.n_vertices() );
2227  pickVertBuf_.resize( mesh_.n_vertices() );
2228 
2229  // Get the right picking colors from the gl state and add them per vertex to the color buffer
2230  typename Mesh::ConstVertexIter v_it(mesh_.vertices_begin()), v_end(mesh_.vertices_end());
2231  for (; v_it!=v_end; ++v_it, ++idx)
2232  {
2233  pickAnyVertexColBuf_[idx] = _state.pick_get_name_color(idx + mesh_.n_faces() + mesh_.n_edges());
2234  pickVertBuf_[idx] = mesh_.point(mesh_.vertex_handle(idx));
2235  }
2236 }
2237 
2238 
2239 
2240 template <class Mesh>
2242 {
2243  updatePickingFaces_opt(_state);
2244  updatePickingEdges_opt(_state);
2245  updatePickingVertices_opt(_state);
2246 
2247  // optimized any picking does not require separate picking buffers
2248 }
2249 
2250 template <class Mesh>
2252 {
2253  return supportsPickingFaces_opt() && supportsPickingEdges_opt() && supportsPickingVertices_opt();
2254 }
2255 
2256 
2257 template <class Mesh>
2258 void ACG::DrawMeshT<Mesh>::drawPickingAny_opt( const GLMatrixf& _mvp, int _pickOffset )
2259 {
2260  // optimized version which computes picking ids in the shader
2261 
2262  /* optimization:
2263  draw picking ids of faces, edges and vertices with appropriate offsets
2264  */
2265 
2266  // test support by loading and compiling picking shader
2267  if (!supportsPickingAny_opt())
2268  return;
2269 
2270  drawPickingFaces_opt(_mvp, _pickOffset);
2271 
2272  ACG::GLState::depthFunc(GL_LEQUAL);
2273 
2274  drawPickingEdges_opt(_mvp, _pickOffset + mesh_.n_faces());
2275 
2276  drawPickingVertices_opt(_mvp, _pickOffset + mesh_.n_faces() + mesh_.n_edges());
2277 }
2278 
2279 template <class Mesh>
2280 void
2282 setTextureIndexPropertyName( std::string _indexPropertyName ) {
2283 
2284  // Check if the given property exists
2285  OpenMesh::FPropHandleT< int > textureIndexProperty;
2286  if ( !mesh_.get_property_handle(textureIndexProperty,_indexPropertyName) ) {
2287  if ( _indexPropertyName != "No Texture Index" )
2288  std::cerr << "DrawMeshT: Unable to get per face texture Index property named " << _indexPropertyName << std::endl;
2289  return;
2290  }
2291 
2292  // Remember the property name
2293  textureIndexPropertyName_ = _indexPropertyName;
2294 
2295  // mark strips as invalid ( have to be regenerated to collect texture index information)
2296 // stripsValid_ = false;
2297 //
2298 // // mark the buffers as invalid as we have a new per face index array
2299 // invalidatePerFaceBuffers();
2300  rebuild_ |= REBUILD_TOPOLOGY;
2301 }
2302 
2303 template <class Mesh>
2304 void
2306 setPerFaceTextureCoordinatePropertyName( std::string _perFaceTextureCoordinatePropertyName ) {
2307 
2308  // Check if the given property exists
2309  OpenMesh::HPropHandleT< typename Mesh::TexCoord2D > perFaceTextureCoordinateProperty;
2310  if ( !mesh_.get_property_handle(perFaceTextureCoordinateProperty,_perFaceTextureCoordinatePropertyName) ) {
2311  if ( _perFaceTextureCoordinatePropertyName != "No Texture" )
2312  std::cerr << "DrawMeshT: Unable to get per face texture coordinate property named " << _perFaceTextureCoordinatePropertyName << std::endl;
2313  return;
2314  }
2315 
2316  // Remember the property name
2317  perFaceTextureCoordinatePropertyName_ = _perFaceTextureCoordinatePropertyName;
2318 
2319  // mark the buffers as invalid as we have a new per face index array
2320 // invalidatePerFaceBuffers();
2321  rebuild_ |= REBUILD_GEOMETRY;
2322 }
2323 
2324 
2325 template <class Mesh>
2327 {
2328  unsigned int n = 0;
2329  for (unsigned int i = 0; i < meshComp_->getNumSubsets(); ++i)
2330  {
2331  if (meshComp_->getSubset(i)->id > 0) ++n;
2332  }
2333  return n;
2334 }
2335 
2336 template <class Mesh>
2337 int
2339 
2340  // We really have to recheck, as the property might get lost externally (e.g. on restores of the mesh)
2341  OpenMesh::HPropHandleT< typename Mesh::TexCoord2D > perFaceTextureCoordinateProperty;
2342  if ( !mesh_.get_property_handle(perFaceTextureCoordinateProperty, perFaceTextureCoordinatePropertyName_) ) {
2343  return false;
2344  }
2345 
2346  // Property available
2347  return true;
2348 
2349 }
2350 
2351 
2352 template <class Mesh>
2353 int
2355 
2356  // We really have to recheck, as the property might get lost externally (e.g. on restores of the mesh)
2357  OpenMesh::FPropHandleT< int > textureIndexProperty;
2358  if ( !mesh_.get_property_handle(textureIndexProperty, textureIndexPropertyName_) ) {
2359  return false;
2360  }
2361 
2362  // Property available
2363  return true;
2364 }
2365 
2366 
2367 
2368 
2369 
2370 
2371 template <class Mesh>
2373 {
2374  vertexDecl_->clear();
2375 
2376  vertexDecl_->addElement(GL_FLOAT, 3, VERTEX_USAGE_POSITION);
2377  vertexDecl_->addElement(GL_FLOAT, 2, VERTEX_USAGE_TEXCOORD);
2378  vertexDecl_->addElement(GL_FLOAT, 3, VERTEX_USAGE_NORMAL);
2379  vertexDecl_->addElement(GL_UNSIGNED_BYTE, 4, VERTEX_USAGE_COLOR);
2380 
2381  for (size_t i = 0; i < additionalElements_.size(); ++i)
2382  {
2383  VertexProperty* prop = &additionalElements_[i];
2384 
2385  // invalidate detected type
2386  prop->sourceType_.numElements_ = 0;
2387  prop->sourceType_.pointer_ = 0;
2388  prop->sourceType_.type_ = 0;
2389  prop->sourceType_.shaderInputName_ = 0;
2391  prop->propDataPtr_ = 0;
2392  prop->declElementID_ = -1;
2393 
2394  // get property handle in openmesh by name
2395  OpenMesh::BaseProperty* baseProp = 0;
2396 
2397  switch (prop->source_)
2398  {
2399  case PROPERTY_SOURCE_VERTEX: baseProp = mesh_._get_vprop(prop->name_); break;
2400  case PROPERTY_SOURCE_FACE: baseProp = mesh_._get_fprop(prop->name_); break;
2401  case PROPERTY_SOURCE_HALFEDGE: baseProp = mesh_._get_hprop(prop->name_); break;
2402  default: baseProp = mesh_._get_vprop(prop->name_); break;
2403  }
2404 
2405  // detect data type of property
2406  prop->propDataPtr_ = getMeshPropertyType(baseProp, &prop->sourceType_.type_, &prop->sourceType_.numElements_);
2407 
2408 
2409  if (prop->propDataPtr_)
2410  {
2411  prop->sourceType_.shaderInputName_ = prop->name_.c_str();
2412 
2413  // should have same type in vbo
2414  prop->destType_ = prop->sourceType_;
2415 
2416  prop->destType_.shaderInputName_ = prop->vertexShaderInputName_.c_str();
2417 
2418  prop->declElementID_ = int(vertexDecl_->getNumElements());
2419 
2420  vertexDecl_->addElement(&prop->destType_);
2421  }
2422  else
2423  std::cerr << "Could not detect data type of property " << prop->name_ << std::endl;
2424  }
2425 }
2426 
2427 
2428 template <class Mesh>
2430 {
2431  vertexDeclEdgeCol_->clear();
2432  vertexDeclEdgeCol_->addElement(GL_FLOAT, 3, VERTEX_USAGE_POSITION, perEdgeVertexBuffer());
2433  vertexDeclEdgeCol_->addElement(GL_FLOAT, 4, VERTEX_USAGE_COLOR, perEdgeColorBuffer());
2434 
2435  vertexDeclHalfedgeCol_->clear();
2436  vertexDeclHalfedgeCol_->addElement(GL_FLOAT, 3, VERTEX_USAGE_POSITION, perHalfedgeVertexBuffer());
2437  vertexDeclHalfedgeCol_->addElement(GL_FLOAT, 4, VERTEX_USAGE_COLOR, perHalfedgeColorBuffer());
2438 
2439  vertexDeclHalfedgePos_->clear();
2440  vertexDeclHalfedgePos_->addElement(GL_FLOAT, 3, VERTEX_USAGE_POSITION, perHalfedgeVertexBuffer());
2441 
2442  vertexDeclEdgeCol_->setVertexStride(0);
2443  vertexDeclHalfedgeCol_->setVertexStride(0);
2444  vertexDeclHalfedgePos_->setVertexStride(0);
2445 }
2446 
2447 template <class Mesh>
2449 {
2450  return vertexDecl_;
2451 }
2452 
2453 
2454 template<class Mesh>
2455 typename Mesh::HalfedgeHandle ACG::DrawMeshT<Mesh>::mapToHalfedgeHandle(int _vertexId)
2456 {
2457  int faceId = -1, cornerId = -1;
2458 
2459  // map to halfedge handle
2460  if (meshComp_)
2461  meshComp_->mapToOriginalVertexID(_vertexId, faceId, cornerId);
2462 
2463  if (faceId >= 0)
2464  {
2465  typename Mesh::FaceHandle fh = mesh_.face_handle(faceId);
2466  typename Mesh::FaceHalfedgeIter hh_it = mesh_.fh_iter(fh);
2467 
2468  // seek to halfedge
2469  for (int k = 0; k < cornerId && hh_it.is_valid(); ++k )
2470  ++hh_it;
2471 
2472  return *hh_it;
2473  }
2474  else
2475  return typename Mesh::HalfedgeHandle(-1);
2476 }
2477 
2478 
2479 template <class Mesh>
2480 void ACG::DrawMeshT<Mesh>::writeVertexElement( void* _dstBuf, unsigned int _vertex, unsigned int _stride, unsigned int _elementOffset, unsigned int _elementSize, const void* _elementData )
2481 {
2482  // byte offset
2483  unsigned int offset = _vertex * _stride + _elementOffset;
2484 
2485  // write address
2486  char* dst = static_cast<char*>(_dstBuf) + offset;
2487 
2488  // copy
2489  memcpy(dst, _elementData, _elementSize);
2490 }
2491 
2492 template <class Mesh>
2493 void ACG::DrawMeshT<Mesh>::writePosition( unsigned int _vertex, const ACG::Vec3d& _n )
2494 {
2495  // store float3 position
2496  float f3[3] = {float(_n[0]), float(_n[1]), float(_n[2])};
2497 
2498  writeVertexElement(&vertices_[0], _vertex, vertexDecl_->getVertexStride(), 0, 12, f3);
2499 }
2500 
2501 template <class Mesh>
2502 void ACG::DrawMeshT<Mesh>::writeNormal( unsigned int _vertex, const ACG::Vec3d& _n )
2503 {
2504  // store float3 normal
2505  float f3[3] = {float(_n[0]), float(_n[1]), float(_n[2])};
2506 
2507  writeVertexElement(&vertices_[0], _vertex, vertexDecl_->getVertexStride(), offsetNormal_, 12, f3);
2508 }
2509 
2510 
2511 template <class Mesh>
2512 void ACG::DrawMeshT<Mesh>::writeTexcoord( unsigned int _vertex, const ACG::Vec2f& _uv )
2513 {
2514  writeVertexElement(&vertices_[0], _vertex, vertexDecl_->getVertexStride(), offsetTexc_, 8, _uv.data());
2515 }
2516 
2517 template <class Mesh>
2518 void ACG::DrawMeshT<Mesh>::writeColor( unsigned int _vertex, unsigned int _color )
2519 {
2520  writeVertexElement(&vertices_[0], _vertex, vertexDecl_->getVertexStride(), offsetColor_, 4, &_color);
2521 }
2522 
2523 
2524 template <class Mesh>
2525 void ACG::DrawMeshT<Mesh>::writeVertexProperty( unsigned int _vertex, const VertexElement* _elementDesc, const ACG::Vec4f& _propf )
2526 {
2527  unsigned int elementSize = VertexDeclaration::getElementSize(_elementDesc);
2528 
2529  writeVertexElement(&vertices_[0], _vertex, vertexDecl_->getVertexStride(), _elementDesc->getByteOffset(), elementSize, _propf.data());
2530 }
2531 
2532 
2533 
2534 template <class Mesh>
2535 void ACG::DrawMeshT<Mesh>::addVertexElement( const std::string& _propertyName, PropertySource _source )
2536 {
2537  // check if element has already been requested before
2538 
2539  for (size_t i = 0; i < additionalElements_.size(); ++i)
2540  {
2541  if (additionalElements_[i].name_ == _propertyName)
2542  {
2543  additionalElements_[i].source_ = _source;
2544 
2545  return;
2546  }
2547  }
2548 
2549 
2550  // request new property
2551  VertexProperty prop;
2552 
2553  prop.name_ = _propertyName;
2554  prop.source_ = _source;
2555  prop.vertexShaderInputName_ = _propertyName;
2556  // rest of property desc is initialized later in createVertexDeclaration()
2557 
2558  additionalElements_.push_back(prop);
2559 
2560  updateFull();
2561 }
2562 
2563 
2564 template <class Mesh>
2565 bool ACG::DrawMeshT<Mesh>::scanVertexShaderForInput( const std::string& _vertexShaderFile )
2566 {
2567  bool success = true;
2568 
2569  std::ifstream file;
2570 
2571  file.open(_vertexShaderFile.c_str(), std::ios_base::in);
2572 
2573  if (file.is_open())
2574  {
2575  while (!file.eof())
2576  {
2577  char line[0xff];
2578 
2579  file.getline(line, 0xff);
2580 
2581  // get rid of whitespaces at begin/end, and internal padding
2582  QString strLine = line;
2583  strLine = strLine.simplified();
2584 
2585  // pattern matching for vertex input attributes
2586  if (!strLine.startsWith("//") && !strLine.startsWith("*/"))
2587  {
2588 
2589  if (strLine.startsWith("in ") || strLine.contains(" in "))
2590  {
2591  // extract
2592  int semIdx = strLine.indexOf(';');
2593 
2594 
2595  if (semIdx >= 0)
2596  {
2597  // property name = string before semicolon without whitespace
2598 
2599  // remove parts after semicolon
2600  QString strName = strLine;
2601  strName.remove(semIdx, strName.length());
2602 
2603  strName = strName.simplified();
2604 
2605  // property name = string between last whitespace and last character
2606  int lastWhite = strName.lastIndexOf(' ');
2607 
2608  if (lastWhite >= 0)
2609  {
2610  strName.remove(0, lastWhite);
2611 
2612  strName = strName.simplified();
2613 
2614  // check for reserved input attributes
2615  if (strName != "inPosition" &&
2616  strName != "inTexCoord" &&
2617  strName != "inNormal" &&
2618  strName != "inColor")
2619  {
2620  // custom property
2621 
2622  std::string propName = strName.toStdString();
2623 
2624  // choose property source
2625  PropertySource src = PROPERTY_SOURCE_VERTEX;
2626 
2627  if (strLine.contains("flat "))
2628  {
2629  // per face attribute
2630  src = PROPERTY_SOURCE_FACE;
2631 
2632  if (!mesh_._get_fprop(propName))
2633  src = PROPERTY_SOURCE_VERTEX; // face source not available, try vertex next..
2634  }
2635 
2636  if (src == PROPERTY_SOURCE_VERTEX)
2637  {
2638  if (!mesh_._get_vprop(propName))
2639  src = PROPERTY_SOURCE_HALFEDGE; // vertex source not available, try halfedge next..
2640  }
2641 
2642  // prefer halfedge props over vertex props
2643  if (src == PROPERTY_SOURCE_VERTEX)
2644  {
2645  if ( mesh_._get_hprop(propName) && src == PROPERTY_SOURCE_VERTEX)
2646  src = PROPERTY_SOURCE_HALFEDGE;
2647  }
2648 
2649  // error output if property does not exist
2650  if (src == PROPERTY_SOURCE_HALFEDGE && !mesh_._get_hprop(propName))
2651  {
2652  std::cerr << "DrawMesh error - requested property " << propName << " does not exist" << std::endl;
2653  success = false;
2654  }
2655  else
2656  {
2657  addVertexElement(propName, src);
2658  }
2659 
2660  }
2661 
2662  }
2663  }
2664 
2665 
2666  }
2667 
2668  }
2669 
2670  }
2671 
2672 
2673  }
2674 
2675  return success;
2676 }
2677 
2678 template<class Mesh>
2679 void DrawMeshT<Mesh>::dumpObj(const char* _filename) const
2680 {
2681  std::ofstream file;
2682  file.open(_filename);
2683 
2684  if (file.is_open())
2685  {
2686  for (int attrId = 0; attrId < 3; ++attrId)
2687  {
2688  for (int i = 0; i < numVerts_; ++i)
2689  {
2690  // ptr to vertex
2691  const char* v = &vertices_[i * vertexDecl_->getVertexStride()];
2692 
2693  const float* pos = reinterpret_cast<const float*>((const void*)(v + offsetPos_));
2694  const float* n = reinterpret_cast<const float*>((const void*)(v + offsetNormal_));
2695  const float* texc = reinterpret_cast<const float*>((const void*)(v + offsetTexc_));
2696 // unsigned int col = *reinterpret_cast<const unsigned int*>(v + offsetColor_);
2697 
2698  switch (attrId)
2699  {
2700  case 0: file << "v "<<pos[0]<<" "<<pos[1]<<" "<<pos[2]<<"\n"; break;
2701  case 1: file << "vt "<<texc[0]<<" "<<texc[1]<<"\n"; break;
2702  case 2: file << "vn "<<n[0]<<" "<<n[1]<<" "<<n[2]<<"\n"; break;
2703  default: break;
2704  }
2705  }
2706  }
2707 
2708 
2709  for (int i = 0; i < numTris_; ++i)
2710  {
2711  // ptr to triangle
2712  const int* tri = meshComp_->getIndexBuffer() + i*3;
2713 
2714  file << "f "<<tri[0]+1<<"/"<<tri[0]+1<<"/"<<tri[0]+1<<" "<<tri[1]+1<<"/"<<tri[1]+1<<"/"<<tri[1]+1<<" "<<tri[2]+1<<"/"<<tri[2]+1<<"/"<<tri[2]+1<<"\n";
2715  }
2716 
2717  file.close();
2718  }
2719 }
2720 
2721 
2722 
2723 template <class Mesh>
2724 void ACG::DrawMeshT<Mesh>::readVertexFromVBO(unsigned int _vertex, void* _dst)
2725 {
2726  assert(_dst != 0);
2727 
2728  unsigned int stride = vertexDecl_->getVertexStride();
2729 
2730  // byte offset
2731  unsigned int offset = _vertex * stride;
2732 
2733  // copy
2734  memcpy(_dst, &vertices_[offset], stride);
2735 }
2736 
2737 
2738 
2739 
2740 
2741 template <class Mesh>
2743 {
2744  updateFullVBO_ = true;
2745 }
2746 
2747 
2748 template <class Mesh>
2750 {
2751  // update indexed vbo first, in the next step this vbo is resolved into non-indexed
2752  updateGPUBuffers();
2753 
2754  if (updateFullVBO_)
2755  {
2756  MeshCompiler* mc = getMeshCompiler();
2757 
2758  if (mc)
2759  {
2760  int numTris = mc->getNumTriangles();
2761 
2762  // alloc buffer
2763  int numVerts = 3 * numTris;
2764  int stride = mc->getVertexDeclaration()->getVertexStride();
2765  std::vector<char> fullBuf(numVerts * stride);
2766 
2767  // fill buffer
2768  for (int i = 0; i < numTris; ++i)
2769  {
2770  for (int k = 0; k < 3; ++k)
2771  {
2772  int idx = i * 3 + k;
2773  int vertexID = mc->getIndex(idx);
2774  readVertexFromVBO(vertexID, &fullBuf[idx * stride]);
2775 
2776  if (colorMode_ == 2)
2777  {
2778  // read face color
2779 
2780  int faceId = meshComp_->mapToOriginalFaceID(i);
2781  unsigned int fcolor = getFaceColor(mesh_.face_handle(faceId));
2782 
2783  // store face color
2784  writeVertexElement(&fullBuf[0], idx, vertexDecl_->getVertexStride(), offsetColor_, 4, &fcolor);
2785  }
2786 
2787  }
2788  }
2789 
2790  if (!fullBuf.empty())
2791  vboFull_.upload(fullBuf.size(), &fullBuf[0], GL_STATIC_DRAW);
2792 
2793  // clean update flag
2794  updateFullVBO_ = false;
2795  }
2796  }
2797 }
2798 
2799 
2800 
2801 
2802 
2803 }
int getFaceSize(const int _faceID) const
Definition: DrawMeshT.cc:271
Mesh Drawing Class.
Definition: DrawMesh.hh:172
GLuint indexBuffer
Use vertex array object.
const void * propDataPtr_
memory address of property data
Definition: DrawMesh.hh:892
ShaderGenDesc shaderDesc
Drawmode and other shader params.
bool getFaceAttr(const int _faceID, const int _attrID, int *_out) const
Definition: DrawMeshT.cc:345
void updatePickingFaces_opt(ACG::GLState &_state)
Update color picking array for the shader implementation.
Definition: DrawMeshT.cc:2059
int perFaceTextureCoordinateAvailable()
Check if per Face Texture coordinates are available.
Definition: DrawMeshT.cc:2338
Namespace providing different geometric functions concerning angles.
Definition: DBSCANT.cc:51
int * getFaceAttr(const int _faceID, const int _attrID) const
Definition: DrawMeshT.cc:366
void addPointRenderObjects(IRenderer *_renderer, const RenderObject *_baseObj)
render vertices only, deferred draw call
Definition: DrawMeshT.cc:1527
void createVBO()
stores the vertex buffer on the gpu
Definition: DrawMeshT.cc:900
void updateFullVBO()
update the full mesh vbo
Definition: DrawMeshT.cc:2749
static void bindBuffer(GLenum _target, GLuint _buffer)
replaces glBindBuffer, supports locking
Definition: GLState.cc:1764
void addLineRenderObjects(IRenderer *_renderer, const RenderObject *_baseObj)
render the mesh in wireframe mode, deferred draw call
Definition: DrawMeshT.cc:1500
static bool is_trimesh()
Determine whether this is a PolyMeshT or TriMeshT ( This function does not check the per face vertex ...
Definition: TriMeshT.hh:110
Vec4uc pick_get_name_color(unsigned int _idx)
Definition: GLState.cc:1064
void drawPickingAny_opt(const GLMatrixf &_mvp, int _pickOffset)
Optimized rendering of any picking ids with a shader.
Definition: DrawMeshT.cc:2258
Interface class between scenegraph and renderer.
unsigned int countTris(unsigned int *_pOutMaxPolyVerts=0, unsigned int *_pOutNumIndices=0)
Number of triangles after triangulation of the mesh.
Definition: DrawMeshT.cc:1543
Default property class for any type T.
Definition: Property.hh:94
static void bindTexture(GLenum _target, GLuint _buffer)
replaces glBindTexture, supports locking
Definition: GLState.cc:1812
std::string vertexShaderInputName_
input name id in vertex shader
Definition: DrawMesh.hh:883
static void colorPointer(GLint _size, GLenum _type, GLsizei _stride, const GLvoid *_pointer)
replaces glColorPointer, supports locking
Definition: GLState.cc:1906
void dumpObj(const char *_filename) const
dump current vertex/index buffer to wavefront obj
Definition: DrawMeshT.cc:2679
void updatePickingEdges(ACG::GLState &_state, uint _offset=0)
Update color picking array for edges.
Definition: DrawMeshT.cc:1913
void rebuild()
draw_mesh updater
Definition: DrawMeshT.cc:407
GLuint vertexBuffer
VBO, IBO ids, ignored if VAO is provided.
virtual size_t n_elements() const =0
Number of elements in property.
void updatePickingEdges_opt(ACG::GLState &_state)
Update color picking array for the shader implementation.
Definition: DrawMeshT.cc:1938
int getNumIndices() const
Definition: DrawMeshT.cc:266
unsigned int getVertexColor(const typename Mesh::VertexHandle _vh)
return a vertex color from mesh
Definition: DrawMeshT.cc:834
void bindBuffers()
eventually rebuilds buffers used for rendering and binds index and vertex buffer
Definition: DrawMeshT.cc:1301
int getNumTriangles() const
Kernel::Point Point
Coordinate type.
Definition: PolyMeshT.hh:115
void invalidateFullVBO()
the mesh has been changed
Definition: DrawMeshT.cc:2742
void drawVertices()
render vertices only
Definition: DrawMeshT.cc:1515
Handle for a halfedge entity.
Definition: Handles.hh:132
void updatePickingVertices(ACG::GLState &_state, uint _offset=0)
Definition: DrawMeshT.cc:1595
std::string name_
property name in openmesh
Definition: DrawMesh.hh:880
Description of one vertex element.
unsigned int getVertexStride(unsigned int i=0) const
const VertexDeclaration * getVertexDeclaration() const
static void enableClientState(GLenum _cap)
replaces glEnableClientState, supports locking
Definition: GLState.cc:1541
const void * testMeshPropertyTypeT(const OpenMesh::BaseProperty *_prop, unsigned int *_outSize) const
test mesh property for type T
Definition: DrawMeshT.cc:110
GLSL::Program * getProgram(const ShaderGenDesc *_desc, const std::vector< unsigned int > &_mods)
Query a dynamically generated program from cache.
Definition: ShaderCache.cc:108
static unsigned int getElementSize(const VertexElement *_pElement)
void draw(std::map< int, GLuint > *_textureMap, bool _nonindexed=false)
binds index and vertex buffer and executes draw calls
Definition: DrawMeshT.cc:1359
Mesh::Point halfedge_point(const typename Mesh::HalfedgeHandle _heh)
compute halfedge point compute visualization point for halfedge (shifted to interior of face) ...
Definition: DrawMeshT.cc:1851
Kernel::ConstFaceHalfedgeIter ConstFaceHalfedgeIter
Circulator.
Definition: PolyMeshT.hh:181
const VertexDeclaration * vertexDecl
Defines the vertex buffer layout, ignored if VAO is provided.
bool scanVertexShaderForInput(const std::string &_vertexShaderFile)
Scan vertex layout from vertex shader.
Definition: DrawMeshT.cc:2565
void drawPickingFaces_opt(const GLMatrixf &_mvp, int _pickOffset)
Optimized rendering of face picking ids with a shader.
Definition: DrawMeshT.cc:2094
void updatePerEdgeBuffers()
Update all per edge drawing buffers.
Definition: DrawMeshT.cc:1764
void bindBuffersToRenderObject(RenderObject *_obj)
eventually rebuilds buffers used for rendering and binds index and vertex buffer
Definition: DrawMeshT.cc:1331
void createIBO()
stores the index buffer on the gpu
Definition: DrawMeshT.cc:1107
int getSingleFaceAttr(const int _faceID, const int _faceCorner, const int _attrID) const
Definition: DrawMeshT.cc:283
GLuint getIBO()
get opengl index buffer id
Definition: DrawMeshT.cc:1280
void createVertexDeclaration()
creates all vertex declarations needed for deferred draw call renderer
Definition: DrawMeshT.cc:2372
bool isLinked()
Returns if the program object has been succesfully linked.
Definition: GLSLShader.cc:376
VertexDeclaration * getVertexDeclaration()
get vertex declaration of the current vbo layout
Definition: DrawMeshT.cc:2448
ACG::Vec3f * perHalfedgeVertexBuffer()
get a pointer to the per edge vertex buffer
Definition: DrawMeshT.cc:1880
VectorT< float, 3 > Vec3f
Definition: VectorT.hh:125
unsigned int getFaceColor(const typename Mesh::FaceHandle _fh)
return a face color from mesh
Definition: DrawMeshT.cc:856
defined by user via VertexElement::shaderInputName_
void addTriRenderObjects(IRenderer *_renderer, const RenderObject *_baseObj, std::map< int, GLuint > *_textureMap, bool _nonindexed=false)
adds RenderObjects to a deferred draw call renderer
Definition: DrawMeshT.cc:1412
void updatePickingAny(ACG::GLState &_state)
Call this function to update the color picking array.
Definition: DrawMeshT.cc:2165
ACG::Vec4f * perHalfedgeColorBuffer()
get a pointer to the per edge color buffer
Definition: DrawMeshT.cc:1895
static void normalPointer(GLenum _type, GLsizei _stride, const GLvoid *_pointer)
replaces glNormalPointer, supports locking
Definition: GLState.cc:1884
VectorT< unsigned char, 4 > Vec4uc
Definition: VectorT.hh:134
void updatePickingAny_opt(ACG::GLState &_state)
Update color picking array for the shader implementation.
Definition: DrawMeshT.cc:2241
int declElementID_
element id in vertex declaration
Definition: DrawMesh.hh:895
GLSL::Program * pickFaceShader_
optimized face picking shader
Definition: DrawMesh.hh:669
bool supportsPickingEdges_opt()
Check if optimized face picking is supported.
Definition: DrawMeshT.cc:1952
void setTextureIndexPropertyName(std::string _indexPropertyName)
set the name of the property used for texture index specification
Definition: DrawMeshT.cc:2282
static void texcoordPointer(GLint _size, GLenum _type, GLsizei _stride, const GLvoid *_pointer)
replaces glTexcoordPointer, supports locking
Definition: GLState.cc:1928
void unbindBuffers()
disables vertex, normal, texcoord and color pointers in OpenGL
Definition: DrawMeshT.cc:1345
void readVertexFromVBO(unsigned int _vertex, void *_dst)
Read one vertex from the rendering vbo.
Definition: DrawMeshT.cc:2724
void updateEdgeHalfedgeVertexDeclarations()
updates per edge and halfedge vertex declarations
Definition: DrawMeshT.cc:2429
virtual void addRenderObject(RenderObject *_renderObject)
Callback for the scenegraph nodes, which send new render objects via this function.
Definition: IRenderer.cc:105
void updatePickingFaces(ACG::GLState &_state)
Update color picking array for faces.
Definition: DrawMeshT.cc:2014
static ShaderCache * getInstance()
Return instance of the ShaderCache singleton.
Definition: ShaderCache.cc:90
Texture to be used.
unsigned int getNumTextures()
returns the number of used textured of this mesh
Definition: DrawMeshT.cc:2326
unsigned int getMemoryUsage(bool _printReport=false)
measures the size in bytes of allocated memory. eventually prints a report to std::cout ...
Definition: DrawMeshT.cc:1168
Class to define the vertex input layout.
Kernel::ConstVertexFaceIter ConstVertexFaceIter
Circulator.
Definition: PolyMeshT.hh:179
bool supportsPickingFaces_opt()
Check if optimized face picking is supported.
Definition: DrawMeshT.cc:2080
int getVertexAdjCount(const int _vertexID) const
Definition: DrawMeshT.cc:374
unsigned int type_
GL_FLOAT, GL_UNSIGNED_BYTE, GL_INT, ...
void addTexture(const Texture &_t)
adds a texture to stage RenderObjects::numTextures()
static void disableClientState(GLenum _cap)
replaces glDisableClientState, supports locking
Definition: GLState.cc:1555
Kernel::VertexHandle VertexHandle
Handle for referencing the corresponding item.
Definition: PolyMeshT.hh:139
void readVertex(unsigned int _vertex, const typename Mesh::VertexHandle _vh, const typename Mesh::HalfedgeHandle _hh, const typename Mesh::FaceHandle _fh)
reads a vertex from mesh_ and write it to vertex buffer
Definition: DrawMeshT.cc:755
static void vertexPointer(GLint _size, GLenum _type, GLsizei _stride, const GLvoid *_pointer)
replaces glVertexPointer, supports locking
Definition: GLState.cc:1862
ACG::Vec3f * perEdgeVertexBuffer()
get a pointer to the per edge vertex buffer
Definition: DrawMeshT.cc:1576
VertexElement destType_
property type as stored in vbo
Definition: DrawMesh.hh:889
unsigned int numElements_
how many elements of type_
int getTextureIDofTri(unsigned int _tri)
get the texture index of a triangle
Definition: DrawMeshT.cc:892
unsigned int mapVertexToVBOIndex(unsigned int _v)
map from vertex index of the original mesh point buffer to the corresponding vertex index inside the ...
Definition: DrawMeshT.cc:1287
const void * getMeshPropertyType(OpenMesh::BaseProperty *_prop, GLuint *_outType, unsigned int *_outSize) const
get the data type of a mesh property
Definition: DrawMeshT.cc:162
GLuint getVBO()
get opengl vertex buffer id
Definition: DrawMeshT.cc:1273
const T * data() const
Get pointer to array (does not work for T==bool)
Definition: Property.hh:174
VERTEX_USAGE usage_
position, normal, shader input ..
const char * shaderInputName_
set shader input name, if usage_ = VERTEX_USAGE_USER_DEFINED otherwise this is set automatically...
int perFaceTextureIndexAvailable()
Check if texture indices are available.
Definition: DrawMeshT.cc:2354
GLenum indexType
Index element type.
const void * pointer_
Offset in bytes to the first occurrence of this element in vertex buffer; Or address to vertex data i...
bool supportsPickingVertices_opt()
Check if optimized vertex picking is supported.
Definition: DrawMeshT.cc:1667
const GLenum & depthFunc() const
get glDepthFunc() that is supposed to be active
Definition: GLState.cc:937
void setPerFaceTextureCoordinatePropertyName(std::string _perFaceTextureCoordinatePropertyName)
set the name of the property used for texture coordinate
Definition: DrawMeshT.cc:2306
static void bindBufferARB(GLenum _target, GLuint _buffer)
same function as bindBuffer
Definition: GLState.hh:576
void updatePerHalfedgeBuffers()
Update all per edge drawing buffer n The updated buffers are: per edge vertex buffer ( 2 vertices per...
Definition: DrawMeshT.cc:1802
void addVertexElement(const std::string &_propertyName, PropertySource _source=PROPERTY_SOURCE_VERTEX)
Add custom elements to the vertex layout.
Definition: DrawMeshT.cc:2535
void updatePickingVertices_opt(ACG::GLState &_state)
Update color picking array for the shader implementation.
Definition: DrawMeshT.cc:1615
Kernel::FaceHalfedgeIter FaceHalfedgeIter
Circulator.
Definition: PolyMeshT.hh:171
ACG::Vec4f * perEdgeColorBuffer()
get a pointer to the per edge color buffer
Definition: DrawMeshT.cc:1585
int getIndex(int _i) const
bool supportsPickingAny_opt()
Check if optimized any picking is supported.
Definition: DrawMeshT.cc:2251
void drawPickingVertices_opt(const GLMatrixf &_mvp, int _pickOffset)
Optimized rendering of vertex picking ids with a shader.
Definition: DrawMeshT.cc:1692
void drawLines()
render the mesh in wireframe mode
Definition: DrawMeshT.cc:1484
int getTextureIDofFace(unsigned int _face)
get the texture index of a face
Definition: DrawMeshT.cc:878
void drawPickingEdges_opt(const GLMatrixf &_mvp, int _pickOffset)
Optimized rendering of edge picking ids with a shader.
Definition: DrawMeshT.cc:1963
VertexElement sourceType_
property type as stored in openmesh
Definition: DrawMesh.hh:886
void updateGPUBuffers()
eventually update vertex and index buffers
Definition: DrawMeshT.cc:1248
int getVertexAdjFace(const int _vertexID, const int _k) const
Definition: DrawMeshT.cc:388