Developer Documentation

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

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
105 createVertexDeclaration();
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;
118 typedef OpenMesh::PropertyT< OpenMesh::VectorT<T, 1> > PropVec1;
119 typedef OpenMesh::PropertyT< OpenMesh::VectorT<T, 2> > PropVec2;
120 typedef OpenMesh::PropertyT< OpenMesh::VectorT<T, 3> > PropVec3;
121 typedef OpenMesh::PropertyT< OpenMesh::VectorT<T, 4> > PropVec4;
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>
249 class DrawMeshFaceInput : public MeshCompilerFaceInput
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
407 DrawMeshT<Mesh>::rebuild()
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
614 if (el->usage_ == VERTEX_USAGE_SHADER_INPUT)
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
834 DrawMeshT<Mesh>::getVertexColor(const typename Mesh::VertexHandle _vh)
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
878 DrawMeshT<Mesh>::getTextureIDofFace(unsigned int _face)
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
892 DrawMeshT<Mesh>::getTextureIDofTri(unsigned int _tri)
893 {
894 return getTextureIDofFace(meshComp_->mapToOriginalFaceID(_tri));
895 }
896
897
898 template <class Mesh>
899 void
900 DrawMeshT<Mesh>::createVBO()
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
1107 DrawMeshT<Mesh>::createIBO()
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>
1160 DrawMeshT<Mesh>::~DrawMeshT(void)
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>
1248 void DrawMeshT<Mesh>::updateGPUBuffers()
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>
1273 GLuint DrawMeshT<Mesh>::getVBO()
1274 {
1275 updateGPUBuffers();
1276 return vbo_;
1277 }
1278
1279 template <class Mesh>
1280 GLuint DrawMeshT<Mesh>::getIBO()
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>
1301 void DrawMeshT<Mesh>::bindBuffers()
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>
1331 void DrawMeshT<Mesh>::bindBuffersToRenderObject(RenderObject* _obj)
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>
1345 void DrawMeshT<Mesh>::unbindBuffers()
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 {
1442 RenderObject::Texture tex;
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
1454 RenderObject::Texture tex;
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>
1484 void DrawMeshT<Mesh>::drawLines()
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>
1500 void DrawMeshT<Mesh>::addLineRenderObjects(IRenderer* _renderer, const RenderObject* _baseObj)
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>
1515 void DrawMeshT<Mesh>::drawVertices()
1516 {
1517
1518 bindBuffers();
1519
1520 if (numVerts_)
1521 glDrawArrays(GL_POINTS, 0, numVerts_);
1522
1523 unbindBuffers();
1524 }
1525
1526 template <class Mesh>
1527 void DrawMeshT<Mesh>::addPointRenderObjects(IRenderer* _renderer, const RenderObject* _baseObj)
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>
1576 ACG::Vec3f* DrawMeshT<Mesh>::perEdgeVertexBuffer()
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>
1585 ACG::Vec4f* DrawMeshT<Mesh>::perEdgeColorBuffer()
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>
1595 void DrawMeshT<Mesh>::updatePickingVertices(ACG::GLState& _state,
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>
1615 void DrawMeshT<Mesh>::updatePickingVertices_opt(ACG::GLState& _state)
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>
1667 bool ACG::DrawMeshT<Mesh>::supportsPickingVertices_opt()
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>
1764 void DrawMeshT<Mesh>::updatePerEdgeBuffers()
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)>
1802 void DrawMeshT<Mesh>::updatePerHalfedgeBuffers()
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>
1880 ACG::Vec3f* DrawMeshT<Mesh>::perHalfedgeVertexBuffer()
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>
1895 ACG::Vec4f* DrawMeshT<Mesh>::perHalfedgeColorBuffer()
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>
1913 void DrawMeshT<Mesh>::updatePickingEdges(ACG::GLState& _state,
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>
1938 void DrawMeshT<Mesh>::updatePickingEdges_opt(ACG::GLState& _state )
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>
1952 bool ACG::DrawMeshT<Mesh>::supportsPickingEdges_opt()
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>
2014 void DrawMeshT<Mesh>::updatePickingFaces(ACG::GLState& _state )
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>
2059 void DrawMeshT<Mesh>::updatePickingFaces_opt(ACG::GLState& _state )
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>
2080 bool ACG::DrawMeshT<Mesh>::supportsPickingFaces_opt()
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>
2165 void DrawMeshT<Mesh>::updatePickingAny(ACG::GLState& _state )
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>
2241 void DrawMeshT<Mesh>::updatePickingAny_opt(ACG::GLState& _state )
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>
2251 bool ACG::DrawMeshT<Mesh>::supportsPickingAny_opt()
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
2281 DrawMeshT<Mesh>::
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
2305 DrawMeshT<Mesh>::
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>
2326 unsigned int DrawMeshT<Mesh>::getNumTextures()
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
2338 DrawMeshT<Mesh>::perFaceTextureCoordinateAvailable() {
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
2354 DrawMeshT<Mesh>::perFaceTextureIndexAvailable() {
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>
2372 void ACG::DrawMeshT<Mesh>::createVertexDeclaration()
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;
2390 prop->sourceType_.usage_ = VERTEX_USAGE_SHADER_INPUT;
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>
2429 void ACG::DrawMeshT<Mesh>::updateEdgeHalfedgeVertexDeclarations()
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>
2448 VertexDeclaration* ACG::DrawMeshT<Mesh>::getVertexDeclaration()
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>
2742 void ACG::DrawMeshT<Mesh>::invalidateFullVBO()
2743 {
2744 updateFullVBO_ = true;
2745 }
2746
2747
2748 template <class Mesh>
2749 void ACG::DrawMeshT<Mesh>::updateFullVBO()
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 }
ACG::DrawMeshFaceInput::getFaceSize
int getFaceSize(const int _faceID) const
Definition: DrawMeshT.cc:271
ACG::DrawMeshT
Mesh Drawing Class.
Definition: DrawMesh.hh:172
ACG::RenderObject::indexBuffer
GLuint indexBuffer
Use vertex array object.
Definition: RenderObject.hh:169
ACG::DrawMeshT::VertexProperty::propDataPtr_
const void * propDataPtr_
memory address of property data
Definition: DrawMesh.hh:892
ACG::RenderObject::shaderDesc
ShaderGenDesc shaderDesc
Drawmode and other shader params.
Definition: RenderObject.hh:232
ACG::DrawMeshFaceInput::getFaceAttr
bool getFaceAttr(const int _faceID, const int _attrID, int *_out) const
Definition: DrawMeshT.cc:345
ACG::DrawMeshT::updatePickingFaces_opt
void updatePickingFaces_opt(ACG::GLState &_state)
Update color picking array for the shader implementation.
Definition: DrawMeshT.cc:2059
OpenMesh::HPropHandleT
Definition: Property.hh:501
ACG::DrawMeshT::perFaceTextureCoordinateAvailable
int perFaceTextureCoordinateAvailable()
Check if per Face Texture coordinates are available.
Definition: DrawMeshT.cc:2338
ACG
Namespace providing different geometric functions concerning angles.
Definition: DBSCANT.cc:51
ACG::DrawMeshFaceInput::getFaceAttr
int * getFaceAttr(const int _faceID, const int _attrID) const
Definition: DrawMeshT.cc:366
ACG::DrawMeshT::addPointRenderObjects
void addPointRenderObjects(IRenderer *_renderer, const RenderObject *_baseObj)
render vertices only, deferred draw call
Definition: DrawMeshT.cc:1527
ACG::DrawMeshT::createVBO
void createVBO()
stores the vertex buffer on the gpu
Definition: DrawMeshT.cc:900
ACG::DrawMeshT::updateFullVBO
void updateFullVBO()
update the full mesh vbo
Definition: DrawMeshT.cc:2749
ACG::GLState::bindBuffer
static void bindBuffer(GLenum _target, GLuint _buffer)
replaces glBindBuffer, supports locking
Definition: GLState.cc:1764
ACG::VERTEX_USAGE_NORMAL
"inNormal"
Definition: VertexDeclaration.hh:72
ACG::MeshCompiler
Definition: MeshCompiler.hh:246
ACG::DrawMeshT::addLineRenderObjects
void addLineRenderObjects(IRenderer *_renderer, const RenderObject *_baseObj)
render the mesh in wireframe mode, deferred draw call
Definition: DrawMeshT.cc:1500
OpenMesh::TriMeshT::is_trimesh
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
ACG::GLState::pick_get_name_color
Vec4uc pick_get_name_color(unsigned int _idx)
Definition: GLState.cc:1064
ACG::DrawMeshT::drawPickingAny_opt
void drawPickingAny_opt(const GLMatrixf &_mvp, int _pickOffset)
Optimized rendering of any picking ids with a shader.
Definition: DrawMeshT.cc:2258
ACG::RenderObject
Interface class between scenegraph and renderer.
Definition: RenderObject.hh:105
ACG::DrawMeshT::countTris
unsigned int countTris(unsigned int *_pOutMaxPolyVerts=0, unsigned int *_pOutNumIndices=0)
Number of triangles after triangulation of the mesh.
Definition: DrawMeshT.cc:1543
OpenMesh::PropertyT
Default property class for any type T.
Definition: Property.hh:94
ACG::GLState::bindTexture
static void bindTexture(GLenum _target, GLuint _buffer)
replaces glBindTexture, supports locking
Definition: GLState.cc:1812
ACG::VERTEX_USAGE_TEXCOORD
"inTexCoord"
Definition: VertexDeclaration.hh:73
ACG::DrawMeshT::VertexProperty::vertexShaderInputName_
std::string vertexShaderInputName_
input name id in vertex shader
Definition: DrawMesh.hh:883
ACG::GLState::colorPointer
static void colorPointer(GLint _size, GLenum _type, GLsizei _stride, const GLvoid *_pointer)
replaces glColorPointer, supports locking
Definition: GLState.cc:1906
ACG::DrawMeshT::dumpObj
void dumpObj(const char *_filename) const
dump current vertex/index buffer to wavefront obj
Definition: DrawMeshT.cc:2679
ACG::DrawMeshT::updatePickingEdges
void updatePickingEdges(ACG::GLState &_state, uint _offset=0)
Update color picking array for edges.
Definition: DrawMeshT.cc:1913
ACG::DrawMeshT::rebuild
void rebuild()
draw_mesh updater
Definition: DrawMeshT.cc:407
ACG::RenderObject::vertexBuffer
GLuint vertexBuffer
VBO, IBO ids, ignored if VAO is provided.
Definition: RenderObject.hh:169
OpenMesh::BaseProperty::n_elements
virtual size_t n_elements() const =0
Number of elements in property.
ACG::DrawMeshT::updatePickingEdges_opt
void updatePickingEdges_opt(ACG::GLState &_state)
Update color picking array for the shader implementation.
Definition: DrawMeshT.cc:1938
ACG::DrawMeshFaceInput::getNumIndices
int getNumIndices() const
Definition: DrawMeshT.cc:266
ACG::DrawMeshT::getVertexColor
unsigned int getVertexColor(const typename Mesh::VertexHandle _vh)
return a vertex color from mesh
Definition: DrawMeshT.cc:834
ACG::DrawMeshT::bindBuffers
void bindBuffers()
eventually rebuilds buffers used for rendering and binds index and vertex buffer
Definition: DrawMeshT.cc:1301
ACG::MeshCompiler::getNumTriangles
int getNumTriangles() const
Definition: MeshCompiler.hh:593
OpenMesh::PolyMeshT::Point
Kernel::Point Point
Coordinate type.
Definition: PolyMeshT.hh:115
ACG::DrawMeshT::invalidateFullVBO
void invalidateFullVBO()
the mesh has been changed
Definition: DrawMeshT.cc:2742
ACG::DrawMeshT::drawVertices
void drawVertices()
render vertices only
Definition: DrawMeshT.cc:1515
OpenMesh::HalfedgeHandle
Handle for a halfedge entity.
Definition: Handles.hh:132
ACG::GLState
Definition: GLState.hh:220
ACG::DrawMeshT::updatePickingVertices
void updatePickingVertices(ACG::GLState &_state, uint _offset=0)
Definition: DrawMeshT.cc:1595
OpenMesh::TriMesh_ArrayKernelT
Definition: TriMesh_ArrayKernelT.hh:98
ACG::DrawMeshFaceInput
Definition: DrawMeshT.cc:249
ACG::DrawMeshT::VertexProperty::name_
std::string name_
property name in openmesh
Definition: DrawMesh.hh:880
ACG::VertexElement
Description of one vertex element.
Definition: VertexDeclaration.hh:84
ACG::VertexDeclaration::getVertexStride
unsigned int getVertexStride(unsigned int i=0) const
Definition: VertexDeclaration.cc:530
ACG::MeshCompiler::getVertexDeclaration
const VertexDeclaration * getVertexDeclaration() const
Definition: MeshCompiler.hh:611
ACG::GLState::enableClientState
static void enableClientState(GLenum _cap)
replaces glEnableClientState, supports locking
Definition: GLState.cc:1541
ACG::DrawMeshT::testMeshPropertyTypeT
const void * testMeshPropertyTypeT(const OpenMesh::BaseProperty *_prop, unsigned int *_outSize) const
test mesh property for type T
Definition: DrawMeshT.cc:110
ACG::ShaderCache::getProgram
GLSL::Program * getProgram(const ShaderGenDesc *_desc, const std::vector< unsigned int > &_mods)
Query a dynamically generated program from cache.
Definition: ShaderCache.cc:108
ACG::VertexDeclaration::getElementSize
static unsigned int getElementSize(const VertexElement *_pElement)
Definition: VertexDeclaration.cc:344
ACG::DrawMeshT::draw
void draw(std::map< int, GLuint > *_textureMap, bool _nonindexed=false)
binds index and vertex buffer and executes draw calls
Definition: DrawMeshT.cc:1359
ACG::DrawMeshT::halfedge_point
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
OpenMesh::PolyMeshT::ConstFaceHalfedgeIter
Kernel::ConstFaceHalfedgeIter ConstFaceHalfedgeIter
Circulator.
Definition: PolyMeshT.hh:181
ACG::RenderObject::vertexDecl
const VertexDeclaration * vertexDecl
Defines the vertex buffer layout, ignored if VAO is provided.
Definition: RenderObject.hh:215
ACG::IRenderer
Definition: IRenderer.hh:84
ACG::GLMatrixT< float >
ACG::DrawMeshT::scanVertexShaderForInput
bool scanVertexShaderForInput(const std::string &_vertexShaderFile)
Scan vertex layout from vertex shader.
Definition: DrawMeshT.cc:2565
ACG::DrawMeshT::drawPickingFaces_opt
void drawPickingFaces_opt(const GLMatrixf &_mvp, int _pickOffset)
Optimized rendering of face picking ids with a shader.
Definition: DrawMeshT.cc:2094
ACG::DrawMeshT::updatePerEdgeBuffers
void updatePerEdgeBuffers()
Update all per edge drawing buffers.
Definition: DrawMeshT.cc:1764
ACG::DrawMeshT::bindBuffersToRenderObject
void bindBuffersToRenderObject(RenderObject *_obj)
eventually rebuilds buffers used for rendering and binds index and vertex buffer
Definition: DrawMeshT.cc:1331
ACG::DrawMeshT::createIBO
void createIBO()
stores the index buffer on the gpu
Definition: DrawMeshT.cc:1107
ACG::DrawMeshFaceInput::getSingleFaceAttr
int getSingleFaceAttr(const int _faceID, const int _faceCorner, const int _attrID) const
Definition: DrawMeshT.cc:283
ACG::DrawMeshT::getIBO
GLuint getIBO()
get opengl index buffer id
Definition: DrawMeshT.cc:1280
ACG::DrawMeshT::createVertexDeclaration
void createVertexDeclaration()
creates all vertex declarations needed for deferred draw call renderer
Definition: DrawMeshT.cc:2372
GLSL::Program::isLinked
bool isLinked()
Returns if the program object has been succesfully linked.
Definition: GLSLShader.cc:376
ACG::DrawMeshT::getVertexDeclaration
VertexDeclaration * getVertexDeclaration()
get vertex declaration of the current vbo layout
Definition: DrawMeshT.cc:2448
ACG::DrawMeshT::perHalfedgeVertexBuffer
ACG::Vec3f * perHalfedgeVertexBuffer()
get a pointer to the per edge vertex buffer
Definition: DrawMeshT.cc:1880
ACG::Vec3f
VectorT< float, 3 > Vec3f
Definition: VectorT.hh:125
ACG::DrawMeshT::getFaceColor
unsigned int getFaceColor(const typename Mesh::FaceHandle _fh)
return a face color from mesh
Definition: DrawMeshT.cc:856
ACG::VERTEX_USAGE_COLOR
"inColor"
Definition: VertexDeclaration.hh:74
ACG::VERTEX_USAGE_SHADER_INPUT
defined by user via VertexElement::shaderInputName_
Definition: VertexDeclaration.hh:77
ACG::DrawMeshT::addTriRenderObjects
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
ACG::DrawMeshT::updatePickingAny
void updatePickingAny(ACG::GLState &_state)
Call this function to update the color picking array.
Definition: DrawMeshT.cc:2165
ACG::DrawMeshT::perHalfedgeColorBuffer
ACG::Vec4f * perHalfedgeColorBuffer()
get a pointer to the per edge color buffer
Definition: DrawMeshT.cc:1895
ACG::GLState::normalPointer
static void normalPointer(GLenum _type, GLsizei _stride, const GLvoid *_pointer)
replaces glNormalPointer, supports locking
Definition: GLState.cc:1884
ACG::MeshCompiler::Subset
Definition: MeshCompiler.hh:454
ACG::Vec4uc
VectorT< unsigned char, 4 > Vec4uc
Definition: VectorT.hh:134
ACG::DrawMeshT::updatePickingAny_opt
void updatePickingAny_opt(ACG::GLState &_state)
Update color picking array for the shader implementation.
Definition: DrawMeshT.cc:2241
OpenMesh::VectorT
Definition: Vector11T.hh:83
ACG::DrawMeshT::VertexProperty::declElementID_
int declElementID_
element id in vertex declaration
Definition: DrawMesh.hh:895
ACG::VERTEX_USAGE_POSITION
"inPosition"
Definition: VertexDeclaration.hh:71
ACG::DrawMeshT::pickFaceShader_
GLSL::Program * pickFaceShader_
optimized face picking shader
Definition: DrawMesh.hh:669
OpenMesh::BaseProperty
Definition: BaseProperty.hh:65
ACG::DrawMeshT::supportsPickingEdges_opt
bool supportsPickingEdges_opt()
Check if optimized face picking is supported.
Definition: DrawMeshT.cc:1952
ACG::DrawMeshT::setTextureIndexPropertyName
void setTextureIndexPropertyName(std::string _indexPropertyName)
set the name of the property used for texture index specification
Definition: DrawMeshT.cc:2282
ACG::GLState::texcoordPointer
static void texcoordPointer(GLint _size, GLenum _type, GLsizei _stride, const GLvoid *_pointer)
replaces glTexcoordPointer, supports locking
Definition: GLState.cc:1928
ACG::DrawMeshT::unbindBuffers
void unbindBuffers()
disables vertex, normal, texcoord and color pointers in OpenGL
Definition: DrawMeshT.cc:1345
ACG::DrawMeshT::readVertexFromVBO
void readVertexFromVBO(unsigned int _vertex, void *_dst)
Read one vertex from the rendering vbo.
Definition: DrawMeshT.cc:2724
ACG::MeshCompilerFaceInput
Definition: MeshCompiler.hh:134
ACG::DrawMeshT::updateEdgeHalfedgeVertexDeclarations
void updateEdgeHalfedgeVertexDeclarations()
updates per edge and halfedge vertex declarations
Definition: DrawMeshT.cc:2429
ACG::IRenderer::addRenderObject
virtual void addRenderObject(RenderObject *_renderObject)
Callback for the scenegraph nodes, which send new render objects via this function.
Definition: IRenderer.cc:105
ACG::DrawMeshT::updatePickingFaces
void updatePickingFaces(ACG::GLState &_state)
Update color picking array for faces.
Definition: DrawMeshT.cc:2014
ACG::ShaderCache::getInstance
static ShaderCache * getInstance()
Return instance of the ShaderCache singleton.
Definition: ShaderCache.cc:90
ACG::RenderObject::Texture
Texture to be used.
Definition: RenderObject.hh:306
ACG::DrawMeshT::getNumTextures
unsigned int getNumTextures()
returns the number of used textured of this mesh
Definition: DrawMeshT.cc:2326
ACG::DrawMeshT::getMemoryUsage
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
ACG::VertexDeclaration
Class to define the vertex input layout.
Definition: VertexDeclaration.hh:266
OpenMesh::PolyMeshT::ConstVertexFaceIter
Kernel::ConstVertexFaceIter ConstVertexFaceIter
Circulator.
Definition: PolyMeshT.hh:179
ACG::DrawMeshT::supportsPickingFaces_opt
bool supportsPickingFaces_opt()
Check if optimized face picking is supported.
Definition: DrawMeshT.cc:2080
ACG::DrawMeshFaceInput::getVertexAdjCount
int getVertexAdjCount(const int _vertexID) const
Definition: DrawMeshT.cc:374
ACG::VertexElement::type_
unsigned int type_
GL_FLOAT, GL_UNSIGNED_BYTE, GL_INT, ...
Definition: VertexDeclaration.hh:88
ACG::RenderObject::addTexture
void addTexture(const Texture &_t)
adds a texture to stage RenderObjects::numTextures()
Definition: RenderObject.hh:319
ACG::GLState::disableClientState
static void disableClientState(GLenum _cap)
replaces glDisableClientState, supports locking
Definition: GLState.cc:1555
OpenMesh::PolyMeshT::VertexHandle
Kernel::VertexHandle VertexHandle
Handle for referencing the corresponding item.
Definition: PolyMeshT.hh:139
ACG::DrawMeshT::readVertex
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
ACG::GLState::vertexPointer
static void vertexPointer(GLint _size, GLenum _type, GLsizei _stride, const GLvoid *_pointer)
replaces glVertexPointer, supports locking
Definition: GLState.cc:1862
OpenMesh::FPropHandleT
Definition: Property.hh:529
ACG::DrawMeshT::perEdgeVertexBuffer
ACG::Vec3f * perEdgeVertexBuffer()
get a pointer to the per edge vertex buffer
Definition: DrawMeshT.cc:1576
ACG::DrawMeshT::VertexProperty::destType_
VertexElement destType_
property type as stored in vbo
Definition: DrawMesh.hh:889
ACG::VertexElement::numElements_
unsigned int numElements_
how many elements of type_
Definition: VertexDeclaration.hh:89
ACG::DrawMeshT::getTextureIDofTri
int getTextureIDofTri(unsigned int _tri)
get the texture index of a triangle
Definition: DrawMeshT.cc:892
ACG::DrawMeshT::mapVertexToVBOIndex
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
ACG::DrawMeshT::getMeshPropertyType
const void * getMeshPropertyType(OpenMesh::BaseProperty *_prop, GLuint *_outType, unsigned int *_outSize) const
get the data type of a mesh property
Definition: DrawMeshT.cc:162
ACG::DrawMeshT::getVBO
GLuint getVBO()
get opengl vertex buffer id
Definition: DrawMeshT.cc:1273
OpenMesh::PropertyT::data
const T * data() const
Get pointer to array (does not work for T==bool)
Definition: Property.hh:174
ACG::VertexElement::usage_
VERTEX_USAGE usage_
position, normal, shader input ..
Definition: VertexDeclaration.hh:90
ACG::VertexElement::shaderInputName_
const char * shaderInputName_
set shader input name, if usage_ = VERTEX_USAGE_USER_DEFINED otherwise this is set automatically...
Definition: VertexDeclaration.hh:91
ACG::DrawMeshT::perFaceTextureIndexAvailable
int perFaceTextureIndexAvailable()
Check if texture indices are available.
Definition: DrawMeshT.cc:2354
ACG::RenderObject::indexType
GLenum indexType
Index element type.
Definition: RenderObject.hh:204
ACG::VertexElement::pointer_
const void * pointer_
Offset in bytes to the first occurrence of this element in vertex buffer; Or address to vertex data i...
Definition: VertexDeclaration.hh:92
ACG::DrawMeshT::supportsPickingVertices_opt
bool supportsPickingVertices_opt()
Check if optimized vertex picking is supported.
Definition: DrawMeshT.cc:1667
ACG::GLState::depthFunc
const GLenum & depthFunc() const
get glDepthFunc() that is supposed to be active
Definition: GLState.cc:937
ACG::DrawMeshT::setPerFaceTextureCoordinatePropertyName
void setPerFaceTextureCoordinatePropertyName(std::string _perFaceTextureCoordinatePropertyName)
set the name of the property used for texture coordinate
Definition: DrawMeshT.cc:2306
ACG::GLState::bindBufferARB
static void bindBufferARB(GLenum _target, GLuint _buffer)
same function as bindBuffer
Definition: GLState.hh:576
ACG::DrawMeshT::updatePerHalfedgeBuffers
void updatePerHalfedgeBuffers()
Update all per edge drawing buffer n The updated buffers are: per edge vertex buffer ( 2 vertices per...
Definition: DrawMeshT.cc:1802
ACG::DrawMeshT::addVertexElement
void addVertexElement(const std::string &_propertyName, PropertySource _source=PROPERTY_SOURCE_VERTEX)
Add custom elements to the vertex layout.
Definition: DrawMeshT.cc:2535
ACG::DrawMeshT::updatePickingVertices_opt
void updatePickingVertices_opt(ACG::GLState &_state)
Update color picking array for the shader implementation.
Definition: DrawMeshT.cc:1615
OpenMesh::PolyMeshT::FaceHalfedgeIter
Kernel::FaceHalfedgeIter FaceHalfedgeIter
Circulator.
Definition: PolyMeshT.hh:171
ACG::DrawMeshT::perEdgeColorBuffer
ACG::Vec4f * perEdgeColorBuffer()
get a pointer to the per edge color buffer
Definition: DrawMeshT.cc:1585
ACG::MeshCompiler::getIndex
int getIndex(int _i) const
Definition: MeshCompiler.cc:2999
ACG::DrawMeshT::supportsPickingAny_opt
bool supportsPickingAny_opt()
Check if optimized any picking is supported.
Definition: DrawMeshT.cc:2251
ACG::DrawMeshT::VertexProperty
Definition: DrawMesh.hh:874
ACG::DrawMeshT::drawPickingVertices_opt
void drawPickingVertices_opt(const GLMatrixf &_mvp, int _pickOffset)
Optimized rendering of vertex picking ids with a shader.
Definition: DrawMeshT.cc:1692
ACG::DrawMeshT::drawLines
void drawLines()
render the mesh in wireframe mode
Definition: DrawMeshT.cc:1484
ACG::DrawMeshT::getTextureIDofFace
int getTextureIDofFace(unsigned int _face)
get the texture index of a face
Definition: DrawMeshT.cc:878
ACG::DrawMeshT::drawPickingEdges_opt
void drawPickingEdges_opt(const GLMatrixf &_mvp, int _pickOffset)
Optimized rendering of edge picking ids with a shader.
Definition: DrawMeshT.cc:1963
ACG::DrawMeshT::VertexProperty::sourceType_
VertexElement sourceType_
property type as stored in openmesh
Definition: DrawMesh.hh:886
ACG::DrawMeshT::updateGPUBuffers
void updateGPUBuffers()
eventually update vertex and index buffers
Definition: DrawMeshT.cc:1248
ACG::DrawMeshFaceInput::getVertexAdjFace
int getVertexAdjFace(const int _vertexID, const int _k) const
Definition: DrawMeshT.cc:388