Developer Documentation
Loading...
Searching...
No Matches
DrawMeshT_impl.hh
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#define ACG_DRAW_MESH_TCC
45
46//=============================================================================
47
48#include "DrawMesh.hh"
49
50#include <ACG/GL/gl.hh>
51#include <ACG/Geometry/GPUCacheOptimizer.hh>
52#include <ACG/GL/VertexDeclaration.hh>
53#include <ACG/GL/ShaderCache.hh>
54#include <cassert>
55#include <cmath>
56#include <vector>
57#include <map>
58#include <cstring>
59#include <fstream>
60
61#ifdef USE_OPENMP
62#include <omp.h>
63#endif
64
65//=============================================================================
66
67// print a memory usage report each draw call
68//#define DEBUG_MEM_USAGE
69
70
71namespace ACG
72{
73
74template <class Mesh>
75DrawMeshT<Mesh>::DrawMeshT(Mesh& _mesh)
76: mesh_(_mesh),
77 rebuild_(REBUILD_NONE),
78 prevNumFaces_(0), prevNumVerts_(0),
79 colorMode_(1),
80 curVBOColorMode_(1),
81 flatMode_(0), bVBOinFlatMode_(0),
82 textureMode_(1), bVBOinHalfedgeTexMode_(1),
83 halfedgeNormalMode_(0), bVBOinHalfedgeNormalMode_(0),
84 invVertexMap_(0),
85 offsetPos_(0), offsetNormal_(20), offsetTexc_(12), offsetColor_(32),
86 textureIndexPropertyName_("Not Set"),
87 perFaceTextureCoordinatePropertyName_("h:texcoords2D"),
88 updateFullVBO_(true),
89 updatePerEdgeBuffers_(1),
90 updatePerHalfedgeBuffers_(1)
91{
92
93 //today (4.5.2018) the picking shader which uses a textureBuffer, also uses gl_PrimitiveID
94 // since it is only supported since glslversion 150 we can just check for openGLVersion 3.2
95 pickVertexMethod_ = openGLVersionTest(3,2) ? 1 : 0;
96 pickVertexShader_ = 0;
97
98 pickFaceShader_ = 0;
99 pickEdgeShader_ = 0;
100
101 createVertexDeclaration();
102
103 vertexDeclEdgeNew_.addElement(GL_FLOAT, 3, VERTEX_USAGE_POSITION);
104 vertexDeclEdgeNew_.addElement(GL_FLOAT, 4, VERTEX_USAGE_COLOR);
105
106}
107
108template<class Mesh>
109template<class T>
110const void* DrawMeshT<Mesh>::testMeshPropertyTypeT( const OpenMesh::BaseProperty* _prop, unsigned int* _outSize ) const
111{
112 if (_outSize)
113 *_outSize = 0;
114 const void* dataPtr = 0;
115
116 // rtti - detect type of property from openmesh via dynamic_cast
117 typedef OpenMesh::PropertyT< T > Prop1;
122
123 const Prop1* p1 = dynamic_cast<const Prop1*>(_prop);
124 const PropVec1* pv1 = dynamic_cast<const PropVec1*>(_prop);
125 const PropVec2* pv2 = dynamic_cast<const PropVec2*>(_prop);
126 const PropVec3* pv3 = dynamic_cast<const PropVec3*>(_prop);
127 const PropVec4* pv4 = dynamic_cast<const PropVec4*>(_prop);
128
129 if (p1 || pv1)
130 {
131 if (_outSize)
132 *_outSize = 1;
133 if (p1)
134 dataPtr = p1->data();
135 else
136 dataPtr = pv1->data();
137 }
138 else if (pv2)
139 {
140 if (_outSize)
141 *_outSize = 2;
142 dataPtr = pv2->data();
143 }
144 else if (pv3)
145 {
146 if (_outSize)
147 *_outSize = 3;
148 dataPtr = pv3->data();
149 }
150 else if (pv4)
151 {
152 if (_outSize)
153 *_outSize = 4;
154 dataPtr = pv4->data();
155 }
156
157 return dataPtr;
158}
159
160
161template<class Mesh>
162const 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)
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);
229 if (dataPtr)
230 {
231 if (_outType) *_outType = GL_UNSIGNED_SHORT;
232 return dataPtr;
234
235
236 // unknown data type
237 if (_outSize)
238 *_outSize = 0;
239
240 if (_outType)
241 *_outType = 0;
242
243 return 0;
245
246
247
248template<class Mesh>
250{
251
252public:
253
254 explicit DrawMeshFaceInput(Mesh& _mesh) :
255 mesh_(_mesh)
256 {
257 };
259 // map[attrID] -> use per halfedge/vertex attribute (true/false)
260 std::vector<int> attributeStoredPerHalfedge_;
261
263 int getNumFaces() const { return mesh_.n_faces(); }
264
265 // compute number of indices later automatically
266 int getNumIndices() const { return 0; };
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;
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 }
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
399private:
400 Mesh& mesh_;
402
403
404
405template <class Mesh>
406void
408{
409 if (rebuild_ == REBUILD_NONE) return;
410
411 if (!mesh_.n_vertices())
413 numVerts_ = 0;
414 numTris_ = 0;
415 return;
416 }
418
419
420 // --------------------------------------------
421 // debug - request properties
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
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(static_cast<unsigned int>(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())
488 bTriangleRebuild = 1;
489 prevNumFaces_ = mesh_.n_faces();
490 }
491
492 if (prevNumVerts_ != mesh_.n_vertices())
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 (size_t 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 }
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
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
591
592 // points
593 meshComp_->setVertices(mesh_.n_vertices(), mesh_.points(), 24, false, GL_DOUBLE, 3);
594
595 // normals
596 if (halfedgeNormalMode_ && mesh_.has_halfedge_normals())
597 meshComp_->setNormals(mesh_.n_halfedges(), mesh_.property(mesh_.halfedge_normals_pph()).data(), 24, false, GL_DOUBLE, 3);
598 else if (mesh_.has_vertex_normals())
599 meshComp_->setNormals(mesh_.n_vertices(), mesh_.vertex_normals(), 24, false, GL_DOUBLE, 3);
600
601 if (mesh_.has_halfedge_texcoords2D())
602 meshComp_->setTexCoords(mesh_.n_halfedges(), mesh_.htexcoords2D(), 8, false, GL_FLOAT, 2);
603
604 // add more requested custom attribtues to mesh compiler here..
605
606 for (size_t i = 0; i < additionalElements_.size(); ++i)
607 {
608 VertexProperty* propDesc = &additionalElements_[i];
609
610 if (propDesc->declElementID_ >= 0)
611 {
612 const VertexElement* el = vertexDecl_->getElement((unsigned int)propDesc->declElementID_);
613
615 {
616 // get openmesh property handle
617 OpenMesh::BaseProperty* baseProp = 0;
618
619 switch (propDesc->source_)
620 {
621 case PROPERTY_SOURCE_VERTEX: baseProp = mesh_._get_vprop(propDesc->name_); break;
622 case PROPERTY_SOURCE_FACE: baseProp = mesh_._get_fprop(propDesc->name_); break;
623 case PROPERTY_SOURCE_HALFEDGE: baseProp = mesh_._get_hprop(propDesc->name_); break;
624 default: baseProp = mesh_._get_vprop(propDesc->name_); break;
625 }
626
627 if (baseProp)
628 {
629 size_t numAttribs = baseProp->n_elements();
630 const void* attribData = propDesc->propDataPtr_;
632 meshComp_->setAttribVec( propDesc->declElementID_, numAttribs, attribData );
633 }
634
635
636 }
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;
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
739
740
742 // copy to GPU
743
744 createVBO();
745 createIBO();
746
747 bVBOinHalfedgeNormalMode_ = halfedgeNormalMode_;
748
749 rebuild_ = REBUILD_NONE;
750}
751
752
753template <class Mesh>
754void
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);
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())
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
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
832template <class Mesh>
833unsigned int
835{
836 static const typename Mesh::VertexHandle invalidVH(-1);
837
838 unsigned int byteCol;
839
840 Vec4uc vecCol(255, 255, 255, 255);
841
842 if ( _vh != invalidVH && mesh_.has_vertex_colors() )
843 vecCol = OpenMesh::color_cast<Vec4uc, typename Mesh::Color>(mesh_.color(_vh));
844
845 // OpenGL color format: A8B8G8R8
846 byteCol = (unsigned char)(vecCol[0]);
847 byteCol |= ((unsigned char)(vecCol[1])) << 8;
848 byteCol |= ((unsigned char)(vecCol[2])) << 16;
849 byteCol |= ((unsigned char)(vecCol[3])) << 24;
850
851 return byteCol;
852}
853
854template <class Mesh>
855unsigned int
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
876template <class Mesh>
877int
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
890template <class Mesh>
891int
893{
894 return getTextureIDofFace(meshComp_->mapToOriginalFaceID(_tri));
895}
896
897
898template <class Mesh>
899void
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
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 }
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
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())
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);
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) ) );
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
1105template <class Mesh>
1106void
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// glBufferData(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
1159template <class Mesh>
1161{
1162 delete [] invVertexMap_;
1163 delete meshComp_;
1164}
1165
1166
1167
1168template <class Mesh>
1169unsigned int DrawMeshT<Mesh>::getMemoryUsage(bool _printReport)
1170{
1171 unsigned int res = 0;
1172 unsigned int sysBufSize = 0;
1173
1174 sysBufSize += meshComp_->getMemoryUsage();
1175
1176 // vertex buffer
1177 if (!vertices_.empty())
1178 sysBufSize += vertexDecl_->getVertexStride() * numVerts_;
1179
1180
1181
1182 res += sysBufSize;
1183
1184 // mappings
1185 unsigned int mapsSize = 0;
1186
1187 if (invVertexMap_)
1188 res += mesh_.n_vertices() * 4;
1189
1190 res += mapsSize;
1191
1192
1193 // picking buffers
1194 unsigned int pickBufSize = 0;
1195
1196 pickBufSize += pickVertBuf_.capacity() * sizeof(ACG::Vec3f);
1197 pickBufSize += pickVertColBuf_.capacity() * sizeof(ACG::Vec4uc);
1198
1199 pickBufSize += pickEdgeBuf_.capacity() * sizeof(ACG::Vec4uc);
1200
1201 pickBufSize += pickFaceVertexBuf_.capacity() * sizeof(ACG::Vec3f);
1202 pickBufSize += pickFaceColBuf_.capacity() * sizeof(ACG::Vec4uc);
1203
1204
1205 pickBufSize += pickAnyFaceColBuf_.capacity() * sizeof(ACG::Vec4uc);
1206 pickBufSize += pickAnyEdgeColBuf_.capacity() * sizeof(ACG::Vec4uc);
1207 pickBufSize += pickAnyVertexColBuf_.capacity() * sizeof(ACG::Vec4uc);
1208
1209 res += pickBufSize;
1210
1211
1212 // edge and halfedge vertex buffers (glDraw from sysmem)
1213 unsigned int edgeBufSize = 0;
1214
1215 edgeBufSize += perEdgeVertexBuf_.capacity() * sizeof(ACG::Vec3f);
1216 edgeBufSize += perEdgeColorBuf_.capacity() * sizeof(ACG::Vec4uc);
1217
1218 edgeBufSize += perHalfedgeVertexBuf_.capacity() * sizeof(ACG::Vec3f);
1219 edgeBufSize += perHalfedgeColorBuf_.capacity() * sizeof(ACG::Vec4uc);
1220
1221
1222 res += edgeBufSize;
1223
1224
1225 unsigned int gpuBufSize = 0;
1226
1227 if (ibo_)
1228 gpuBufSize += numTris_ * 3 * (indexType_ == GL_UNSIGNED_INT ? 4 : 2);
1229
1230 if (vbo_)
1231 gpuBufSize += numVerts_ * vertexDecl_->getVertexStride();
1232
1233 if (_printReport)
1234 {
1235 std::cout << "\nDrawMesh memory usage in MB:\n";
1236 std::cout << "Vertex+IndexBuffer (SYSMEM only): " << float(sysBufSize) / (1024 * 1024);
1237 std::cout << "\nMappings: " << float(mapsSize) / (1024 * 1024);
1238 std::cout << "\nPicking Buffers: " << float(pickBufSize) / (1024 * 1024);
1239 std::cout << "\nEdge Buffers: " << float(edgeBufSize) / (1024 * 1024);
1240 std::cout << "\nTotal SYSMEM: " << float(res) / (1024 * 1024);
1241 std::cout << "\nTotal GPU: " << float(gpuBufSize) / (1024 * 1024) << std::endl;
1242 }
1243
1244 return res;
1245}
1246
1247
1248template <class Mesh>
1250{
1251 // rebuild if necessary
1252 if ((!numTris_ && mesh_.n_faces())|| ! numVerts_ || (!meshComp_ && mesh_.n_faces()))
1253 {
1254 rebuild_ = REBUILD_FULL;
1255 }
1256
1257 if (bVBOinHalfedgeNormalMode_ != halfedgeNormalMode_) rebuild_ = REBUILD_FULL;
1258
1259 // if no rebuild necessary, check for smooth / flat shading switch
1260 // to update normals
1261 if (rebuild_ == REBUILD_NONE)
1262 {
1263 if (bVBOinFlatMode_ != flatMode_ || bVBOinHalfedgeTexMode_ != textureMode_ || (colorMode_ && curVBOColorMode_ != colorMode_))
1264 createVBO();
1265 }
1266 else
1267 {
1268 rebuild();
1269 }
1270}
1271
1272
1273template <class Mesh>
1275{
1276 updateGPUBuffers();
1277 return vbo_;
1278}
1279
1280template <class Mesh>
1282{
1283 updateGPUBuffers();
1284 return ibo_;
1285}
1286
1287template <class Mesh>
1288unsigned int DrawMeshT<Mesh>::mapVertexToVBOIndex(unsigned int _v)
1289{
1290 if (_v < mesh_.n_vertices())
1291 {
1292 if (invVertexMap_)
1293 return invVertexMap_[_v];
1294 else //if mesh is a point cloud
1295 return _v;
1296 }
1297
1298 return (unsigned int)-1;
1299}
1300
1301template <class Mesh>
1303{
1304 updateGPUBuffers();
1305
1306 ACG::GLState::bindBuffer(GL_ARRAY_BUFFER_ARB, vbo_);
1307
1308 // prepare color mode
1309 if (colorMode_)
1310 {
1311 ACG::GLState::colorPointer(4, GL_UNSIGNED_BYTE, vertexDecl_->getVertexStride(), (char*)offsetColor_);
1312 ACG::GLState::enableClientState(GL_COLOR_ARRAY);
1313 }
1314
1315 // vertex decl
1316 ACG::GLState::vertexPointer(3, GL_FLOAT, vertexDecl_->getVertexStride(), (char*)offsetPos_);
1317 ACG::GLState::enableClientState(GL_VERTEX_ARRAY);
1318
1319 glClientActiveTexture(GL_TEXTURE0);
1320 ACG::GLState::texcoordPointer(2, GL_FLOAT, vertexDecl_->getVertexStride(), (char*)offsetTexc_);
1321 ACG::GLState::enableClientState(GL_TEXTURE_COORD_ARRAY);
1322
1323 ACG::GLState::normalPointer(GL_FLOAT, vertexDecl_->getVertexStride(), (char*)offsetNormal_);
1324 ACG::GLState::enableClientState(GL_NORMAL_ARRAY);
1325
1326// ACG::GLState::normalPointerEXT(3, GL_FLOAT, sizeof(Vertex), (char*)(20)); // ACG::GLState::normalPointerEXT crashes sth. in OpenGL
1327
1328 ACG::GLState::bindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, ibo_);
1329}
1330
1331template <class Mesh>
1333{
1334 updateGPUBuffers();
1335
1336 _obj->vertexBuffer = vbo_;
1337 _obj->indexBuffer = ibo_;
1338
1339 _obj->indexType = indexType_;
1340
1341 // assign correct vertex declaration
1342 _obj->vertexDecl = vertexDecl_;
1343}
1344
1345template <class Mesh>
1347{
1348 ACG::GLState::disableClientState(GL_VERTEX_ARRAY);
1349 ACG::GLState::disableClientState(GL_TEXTURE_COORD_ARRAY);
1350 ACG::GLState::disableClientState(GL_NORMAL_ARRAY);
1351
1352 if (colorMode_)
1353 ACG::GLState::disableClientState(GL_COLOR_ARRAY);
1354
1355 ACG::GLState::bindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
1356 ACG::GLState::bindBuffer(GL_ARRAY_BUFFER_ARB, 0);
1357}
1358
1359template <class Mesh>
1360void DrawMeshT<Mesh>::draw(std::map< int, GLuint>* _textureMap, bool _nonindexed)
1361{
1362 if (!_nonindexed)
1363 bindBuffers();
1364 else
1365 {
1366 updateFullVBO();
1367 vboFull_.bind();
1368 vertexDecl_->activateFixedFunction();
1369 }
1370
1371#ifdef DEBUG_MEM_USAGE
1372 getMemoryUsage(true);
1373#endif
1374
1375 if (numTris_)
1376 {
1377 if (_textureMap)
1378 {
1379 // textured mode
1380
1381 for (int i = 0; i < meshComp_->getNumSubsets(); ++i)
1382 {
1383 const MeshCompiler::Subset* sub = meshComp_->getSubset(i);
1384
1385 if ( _textureMap->find(sub->id) == _textureMap->end() ) {
1386 std::cerr << "Illegal texture index ... trying to access " << sub->id << std::endl;
1387 ACG::GLState::bindTexture(GL_TEXTURE_2D, 0);
1388 }
1389 else
1390 ACG::GLState::bindTexture(GL_TEXTURE_2D, (*_textureMap)[sub->id]);
1391
1392 if (!_nonindexed)
1393 glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(sub->numTris * 3), indexType_,
1394 (GLvoid*)( (size_t)sub->startIndex * (indexType_ == GL_UNSIGNED_INT ? 4 : 2))); // offset in bytes
1395 else
1396 glDrawArrays(GL_TRIANGLES, sub->startIndex, static_cast<GLsizei>(sub->numTris * 3));
1397 }
1398 }
1399 else
1400 {
1401 if (!_nonindexed)
1402 glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(numTris_ * 3), indexType_, 0);
1403 else
1404 glDrawArrays(GL_TRIANGLES, 0, static_cast<GLsizei>(numTris_ * 3));
1405 }
1406 }
1407
1408 unbindBuffers();
1409}
1410
1411
1412template <class Mesh>
1413void ACG::DrawMeshT<Mesh>::addTriRenderObjects(IRenderer* _renderer, const RenderObject* _baseObj, std::map< int, GLuint>* _textureMap, bool _nonindexed)
1414{
1415 if (numTris_)
1416 {
1417 RenderObject ro = *_baseObj;
1418 if (!_nonindexed)
1419 bindBuffersToRenderObject(&ro);
1420 else
1421 {
1422 updateFullVBO();
1423
1424 ro.vertexBuffer = vboFull_.id();
1425 ro.vertexDecl = vertexDecl_;
1426 }
1427
1428 if (_baseObj->shaderDesc.textured())
1429 {
1430 // textured mode
1431
1432 for (int i = 0; i < meshComp_->getNumSubsets(); ++i)
1433 {
1434 const MeshCompiler::Subset* sub = meshComp_->getSubset(i);
1435
1436 if ( _textureMap )
1437 {
1438 if ( _textureMap->find(sub->id) == _textureMap->end() ) {
1439 std::cerr << "Illegal texture index ... trying to access " << sub->id << std::endl;
1440 }
1441 else
1442 {
1444 tex.type = GL_TEXTURE_2D;
1445 tex.id = (*_textureMap)[sub->id];
1446 ro.addTexture(tex,0);
1447 }
1448 }
1449 else // no texture map specified, use whatever texture is currently bound to the first texture stage
1450 {
1451 GLState::activeTexture(GL_TEXTURE0);
1452 GLint textureID = 0;
1453 glGetIntegerv(GL_TEXTURE_BINDING_2D, &textureID);
1454
1456 tex.type = GL_TEXTURE_2D;
1457 tex.id = textureID;
1458 ro.addTexture(tex,0);
1459 }
1460
1461
1462
1463 if (!_nonindexed)
1464 ro.glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(sub->numTris * 3), indexType_,
1465 (GLvoid*)((size_t)sub->startIndex * (indexType_ == GL_UNSIGNED_INT ? 4 : 2))); // offset in bytes
1466 else
1467 ro.glDrawArrays(GL_TRIANGLES, sub->startIndex, static_cast<GLsizei>(sub->numTris * 3) );
1468
1469 _renderer->addRenderObject(&ro);
1470 }
1471 }
1472 else
1473 {
1474 if (!_nonindexed)
1475 ro.glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(numTris_ * 3), indexType_, 0);
1476 else
1477 ro.glDrawArrays(GL_TRIANGLES,0, static_cast<GLsizei>(numTris_ * 3));
1478 _renderer->addRenderObject(&ro);
1479 }
1480 }
1481}
1482
1483
1484template <class Mesh>
1486{
1487 bindBuffers();
1488
1489 if (mesh_.n_edges())
1490 {
1491 ACG::GLState::bindBuffer(GL_ELEMENT_ARRAY_BUFFER, lineIBO_);
1492
1493 glDrawElements(GL_LINES, static_cast<GLsizei>(mesh_.n_edges() * 2), indexType_, 0);
1494 }
1495
1496 unbindBuffers();
1497}
1498
1499
1500template <class Mesh>
1502{
1503 updatePerEdgeBuffersNew();
1504 if (!mesh_.n_edges())
1505 return;
1506 RenderObject ro = *_baseObj;
1507 ro.vertexBuffer = vboEdges_.id();
1508 ro.vertexDecl = &vertexDeclEdgeNew_;
1509 ro.glDrawArrays(GL_LINES, 0, static_cast<GLsizei>(mesh_.n_edges() * 2));
1510 _renderer->addRenderObject(&ro);
1511}
1512
1513template <class Mesh>
1515{
1516
1517 bindBuffers();
1518
1519 if (numVerts_)
1520 glDrawArrays(GL_POINTS, 0, static_cast<GLsizei>(numVerts_));
1521
1522 unbindBuffers();
1523}
1524
1525template <class Mesh>
1527{
1528 RenderObject ro = *_baseObj;
1529 bindBuffersToRenderObject(&ro);
1530
1531 if (numVerts_)
1532 {
1533 ro.glDrawArrays(GL_POINTS, 0, static_cast<GLsizei>(numVerts_));
1534
1535 _renderer->addRenderObject(&ro);
1536 }
1537}
1538
1540
1541template <class Mesh>
1542unsigned int DrawMeshT<Mesh>::countTris(unsigned int* pMaxVertsOut, unsigned int* _pOutNumIndices)
1543{
1544 unsigned int triCounter = 0;
1545
1546 if (pMaxVertsOut) *pMaxVertsOut = 0;
1547 if (_pOutNumIndices) *_pOutNumIndices = 0;
1548
1549 for (unsigned int i = 0; i < mesh_.n_faces(); ++i)
1550 {
1551 typename Mesh::FaceHandle fh = mesh_.face_handle(i);
1552
1553 // count vertices
1554 unsigned int nPolyVerts = 0;
1555
1556 for (typename Mesh::FaceHalfedgeIter hh_it = mesh_.fh_iter(fh); hh_it.is_valid(); ++hh_it ) ++nPolyVerts;
1557
1558 triCounter += (nPolyVerts - 2);
1559
1560 if (pMaxVertsOut)
1561 {
1562 if (*pMaxVertsOut < nPolyVerts)
1563 *pMaxVertsOut = nPolyVerts;
1564 }
1565
1566 if (_pOutNumIndices) *_pOutNumIndices += nPolyVerts;
1567 }
1568
1569 return triCounter;
1570}
1571
1572
1573
1574template <class Mesh>
1576{
1577 // Force update of the buffers if required
1578 if (updatePerEdgeBuffers_)
1579 updatePerEdgeBuffers();
1580 return perEdgeVertexBuf_.empty() ? 0 : &(perEdgeVertexBuf_[0]);
1581}
1582
1583template <class Mesh>
1585{
1586 // Force update of the buffers if required
1587 if (updatePerEdgeBuffers_)
1588 updatePerEdgeBuffers();
1589 return perEdgeColorBuf_.empty() ? 0 : &(perEdgeColorBuf_[0]);
1590}
1591
1592
1593template <class Mesh>
1595 uint _offset)
1596{
1597 unsigned int idx = 0;
1598
1599 // Adjust size of the color buffer to the number of vertices in the mesh
1600 pickVertColBuf_.resize( mesh_.n_vertices() );
1601 pickVertBuf_.resize( mesh_.n_vertices() );
1602
1603 // Get the right picking colors from the gl state and add them per vertex to the color buffer
1604 typename Mesh::ConstVertexIter v_it(mesh_.vertices_begin()), v_end(mesh_.vertices_end());
1605 for (; v_it!=v_end; ++v_it, ++idx)
1606 {
1607 pickVertColBuf_[idx] = _state.pick_get_name_color(idx + _offset);
1608 pickVertBuf_[idx] = mesh_.point(mesh_.vertex_handle(idx));
1609 }
1610}
1611
1612
1613template <class Mesh>
1615{
1616 // Make sure, the face buffers are up to date before generating the picking data!
1617 if (!numVerts_ && mesh_.n_vertices())
1618 {
1619 rebuild_ = REBUILD_FULL;
1620 rebuild();
1621 }
1622
1623 if (numVerts_)
1624 {
1625 // upload vbo id->openmesh id lookup-table to texture buffer
1626
1627 if (pickVertexMethod_ == 0)
1628 {
1629 std::vector<int> forwardMap(numVerts_, 0);
1630
1631 for (int i = 0; i < (int)numVerts_; ++i)
1632 {
1633 int vboIdx = mapVertexToVBOIndex(i);
1634 if (vboIdx >= 0)
1635 forwardMap[vboIdx] = i;
1636 }
1637 pickVertexMapTBO_.setBufferData(sizeof(int) * numVerts_, &forwardMap[0], GL_R32I, GL_STATIC_DRAW);
1638
1639 }
1640 else
1641 {
1642 // Another method: draw with index buffer, which contains the mapping from openmesh vertex id to drawmesh vbo vertex.
1643 // problem with this: gl_VertexID is affected by index buffer and thus represents the drawmesh vbo ids
1644 // -> use gl_PrimitiveID instead, which represents the openmesh vertex id
1645 if (invVertexMap_)
1646 {
1647 bindPickVertexIbo();
1648 fillInvVertexMap(mesh_.n_vertices(), invVertexMap_);
1649 ACG::GLState::bindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
1650 }
1651
1652 }
1653 }
1654}
1655
1656
1657template <class Mesh>
1659{
1660 // load and compile picking shader if necessary
1661 // use shaderGenDesc to generate shaders for better shader compatibility
1662 static ShaderGenDesc desc;
1663 // load from cache
1664 if (pickVertexMethod_ == 0)
1665 {
1666 desc.fragmentTemplateFile = "Picking/pick_vertices_fs.glsl";
1667 desc.vertexTemplateFile = "Picking/pick_vertices_vs.glsl";
1668 }
1669 else
1670 {
1671 desc.fragmentTemplateFile = "Picking/pick_vertices_fs2.glsl";
1672 desc.vertexTemplateFile = "Picking/vertex.glsl";
1673 }
1674 pickVertexShader_ = ShaderCache::getInstance()->getProgram(&desc,nullptr);
1675
1676 // check link status
1677 return pickVertexShader_ && pickVertexShader_->isLinked();
1678}
1679
1680
1681template <class Mesh>
1682void ACG::DrawMeshT<Mesh>::drawPickingVertices_opt( const GLMatrixf& _mvp, size_t _pickOffset )
1683{
1684 // optimized version which computes picking ids in the shader
1685
1686 /*
1687 pickVertexMethod_
1688 0: - create a textureBuffer containing the mapping from vbo id to openmesh vertex id
1689 - draw point list of the main vbo and read texture map in the vertex shader
1690 - computation in vertex shader via gl_VertexID
1691 -> required mem: 4 bytes per vertex in draw vbo
1692 -> # vertex transforms: vertex count in draw vbo
1693
1694 1: - create index buffer containing the mapping from openmesh vertex id to vbo id
1695 (not required for point-clouds)
1696 - draw point list with index buffer
1697 - computation in fragment shader via gl_PrimitiveID
1698 -> required mem: nothing for point-clouds, otherwise 4 bytes per vertex in openmesh
1699 -> # vertex transforms: vertex count in openmesh
1700
1701 method 1 is probably more efficient overall
1702 */
1703
1704 // test support by loading and compiling picking shader
1705 if (!supportsPickingVertices_opt())
1706 return;
1707
1708 ACG::GLState::bindBufferARB(GL_ARRAY_BUFFER_ARB, getVBO());
1709
1710 if (pickVertexMethod_ == 1 && invVertexMap_)
1711 bindPickVertexIbo();
1712
1713 // setup picking shader
1714 pickVertexShader_->use();
1715 getVertexDeclaration()->activateShaderPipeline(pickVertexShader_);
1716
1717 pickVertexShader_->setUniform("pickVertexOffset", static_cast<GLint>(_pickOffset) );
1718
1719 if (pickVertexMethod_ == 0)
1720 {
1721 pickVertexShader_->setUniform("vboToInputMap", 0);
1722 pickVertexMap_opt()->bind(GL_TEXTURE0);
1723 }
1724
1725 pickVertexShader_->setUniform("mWVP", _mvp);
1726
1727 // draw call
1728 if (pickVertexMethod_ == 0)
1729 glDrawArrays(GL_POINTS, 0, static_cast<GLsizei>(getNumVerts()));
1730 else
1731 {
1732 if (pickVertexIBO_opt() && invVertexMap_)
1733 glDrawElements(GL_POINTS, static_cast<GLsizei>(mesh_.n_vertices()), GL_UNSIGNED_INT, 0);
1734 else
1735 glDrawArrays(GL_POINTS, 0, static_cast<GLsizei>(mesh_.n_vertices()));
1736 }
1737
1738 // restore gl state
1739 getVertexDeclaration()->deactivateShaderPipeline(pickVertexShader_);
1740 pickVertexShader_->disable();
1741
1742 // unbind draw buffers
1743 ACG::GLState::bindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
1744
1745 if (pickVertexMethod_ == 1)
1746 ACG::GLState::bindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
1747}
1748
1749
1750
1751template <class Mesh>
1753{
1754 // Only update buffers if they are invalid
1755 if (!updatePerEdgeBuffers_)
1756 return;
1757
1758 perEdgeVertexBuf_.resize(mesh_.n_edges() * 2);
1759
1760 if ( mesh_.has_edge_colors() ) {
1761 perEdgeColorBuf_.resize(mesh_.n_edges() * 2);
1762 } else
1763 perEdgeColorBuf_.clear();
1764
1765 unsigned int idx = 0;
1766
1767 typename Mesh::ConstEdgeIter e_it(mesh_.edges_sbegin()), e_end(mesh_.edges_end());
1768 for (; e_it!=e_end; ++e_it) {
1769
1770 perEdgeVertexBuf_[idx] = mesh_.point(mesh_.to_vertex_handle(mesh_.halfedge_handle(*e_it, 0)));
1771 perEdgeVertexBuf_[idx+1] = mesh_.point(mesh_.to_vertex_handle(mesh_.halfedge_handle(*e_it, 1)));
1772
1773 if ( mesh_.has_edge_colors() ) {
1774 const Vec4f color = OpenMesh::color_cast<Vec4f>( mesh_.color(*e_it) ) ;
1775 perEdgeColorBuf_[ idx ] = color;
1776 perEdgeColorBuf_[ idx + 1 ] = color;
1777 }
1778
1779 idx += 2;
1780 }
1781
1782
1783 updatePerEdgeBuffers_ = 0;
1784
1785 updateEdgeHalfedgeVertexDeclarations();
1786}
1787
1788template <class Mesh>
1790{
1791 if (!updatePerEdgeBuffers_)
1792 return;
1793 perEdgeBuf_.clear();
1794 perEdgeBuf_.reserve(mesh_.n_edges() * 2 * (3 + 4));
1795 auto push_vec4 = [this](const Vec4f &v) {
1796 perEdgeBuf_.push_back(v[0]);
1797 perEdgeBuf_.push_back(v[1]);
1798 perEdgeBuf_.push_back(v[2]);
1799 perEdgeBuf_.push_back(v[3]);
1800 };
1801 auto push_vec3 = [this](const Vec3d &v) {
1802 perEdgeBuf_.push_back(v[0]);
1803 perEdgeBuf_.push_back(v[1]);
1804 perEdgeBuf_.push_back(v[2]);
1805 };
1806 bool have_edge_colors = mesh_.has_edge_colors();
1807 Vec4f color {0.f, 1.f, 0.f, 1.f}; // dummy color, should never be rendered
1808 for (const auto &eh: mesh_.edges()) {
1809 if (have_edge_colors) {
1810 color = OpenMesh::color_cast<Vec4f>(mesh_.color(eh));
1811 }
1812 auto heh = mesh_.halfedge_handle(eh, 0);
1813 ACG::Vec3d pos_from = mesh_.point(mesh_.from_vertex_handle(heh));
1814 ACG::Vec3d pos_to = mesh_.point(mesh_.to_vertex_handle(heh));
1815 push_vec3(pos_from);
1816 push_vec4(color);
1817 push_vec3(pos_to);
1818 push_vec4(color);
1819 }
1820
1821 vboEdges_.upload(
1822 perEdgeBuf_.size() * sizeof(perEdgeBuf_[0]),
1823 static_cast<GLvoid*>(perEdgeBuf_.data()),
1824 GL_STATIC_DRAW);
1825
1826
1827 updatePerEdgeBuffers_ = 0;
1828}
1829
1830template <class Mesh>
1831template<typename Mesh::Normal (DrawMeshT<Mesh>::*NormalLookup)(typename Mesh::FaceHandle)>
1833{
1834 // Only update buffers if they are invalid
1835 if (!updatePerHalfedgeBuffers_)
1836 return;
1837
1838 perHalfedgeVertexBuf_.resize(mesh_.n_halfedges() * 2);
1839
1840 if ( mesh_.has_halfedge_colors() ) {
1841 perHalfedgeColorBuf_.resize(mesh_.n_halfedges() * 2);
1842 } else
1843 perHalfedgeColorBuf_.clear();
1844
1845 unsigned int idx = 0;
1846
1847 for (typename Mesh::ConstHalfedgeIter he_it(mesh_.halfedges_sbegin()), he_end(mesh_.halfedges_end());
1848 he_it != he_end; ++he_it) {
1849
1850 typename Mesh::HalfedgeHandle next_heh = mesh_.next_halfedge_handle(*he_it);
1851 typename Mesh::HalfedgeHandle previous_heh = mesh_.prev_halfedge_handle(*he_it);
1852
1853 if (mesh_.is_valid_handle(next_heh) && mesh_.is_valid_handle(previous_heh))
1854 {
1855 perHalfedgeVertexBuf_[idx] = halfedge_point<NormalLookup>(*he_it);
1856 perHalfedgeVertexBuf_[idx+1] = halfedge_point<NormalLookup>(previous_heh);
1857 }
1858 else
1859 {
1860 // Cannot compute shifted vertex positions. Use original vertex positions instead.
1861 perHalfedgeVertexBuf_[idx ] = mesh_.point(mesh_.to_vertex_handle(*he_it));
1862 perHalfedgeVertexBuf_[idx+1] = mesh_.point(mesh_.from_vertex_handle(*he_it));
1863 }
1864
1865 if ( mesh_.has_halfedge_colors() ) {
1866 const Vec4f color = OpenMesh::color_cast<Vec4f>( mesh_.color(*he_it) ) ;
1867 perHalfedgeColorBuf_[ idx ] = color;
1868 perHalfedgeColorBuf_[ idx + 1 ] = color;
1869 }
1870 idx += 2;
1871 }
1872
1873 if(perHalfedgeVertexBuf_.size() > 0)
1874 {
1875 fillHEVBO(perHalfedgeVertexBuf_.size(), sizeof(perHalfedgeVertexBuf_[0]), perHalfedgeVertexBuf_.data());
1876 }
1877
1878 updatePerHalfedgeBuffers_ = 0;
1879
1880 updateEdgeHalfedgeVertexDeclarations();
1881}
1882
1883template<class Mesh>
1884template<typename Mesh::Normal (DrawMeshT<Mesh>::*NormalLookup)(typename Mesh::FaceHandle)>
1886
1887 typename Mesh::Point p = mesh_.point(mesh_.to_vertex_handle (_heh));
1888 typename Mesh::Point pp = mesh_.point(mesh_.from_vertex_handle(_heh));
1889 typename Mesh::Point pn = mesh_.point(mesh_.to_vertex_handle(mesh_.next_halfedge_handle(_heh)));
1890
1891 // typename Mesh::Point n = (p-pp)%(pn-p);
1892 typename Mesh::Point fn;
1893 if( !mesh_.is_boundary(_heh))
1894 //fn = mesh_.normal(mesh_.face_handle(_heh));
1895 fn = (this->*NormalLookup)(mesh_.face_handle(_heh));
1896 else
1897 //fn = mesh_.normal(mesh_.face_handle(mesh_.opposite_halfedge_handle(_heh)));
1898 fn = (this->*NormalLookup)(mesh_.face_handle(mesh_.opposite_halfedge_handle(_heh)));
1899
1900 typename Mesh::Point upd = ((fn%(pn-p)).normalize() + (fn%(p-pp)).normalize()).normalize();
1901
1902 upd *= ((pn-p).norm()+(p-pp).norm())*0.08;
1903
1904 return (p+upd);
1905
1906 // double alpha = 0.1;
1907 // // correct weighting for concave triangles (or at concave boundaries)
1908 // if( (fn | n) < 0.0) alpha *=-1.0;
1909
1910 // return (p*(1.0-2.0*alpha) + pp*alpha + pn*alpha);
1911}
1912
1913template <class Mesh>
1915{
1916 // Force update of the buffers if required
1917 if (updatePerHalfedgeBuffers_) {
1918 if (mesh_.has_face_normals())
1919 updatePerHalfedgeBuffers<&DrawMeshT::cachedNormalLookup>();
1920 else if (mesh_.is_trimesh())
1921 updatePerHalfedgeBuffers<&DrawMeshT::computedTriMeshNormal>();
1922 else
1923 updatePerHalfedgeBuffers<&DrawMeshT::computedNormal>();
1924 }
1925 return perHalfedgeVertexBuf_.empty() ? 0 : &(perHalfedgeVertexBuf_[0]);
1926}
1927
1928template <class Mesh>
1930{
1931 // Force update of the buffers if required
1932 if (updatePerHalfedgeBuffers_) {
1933 if (mesh_.has_face_normals())
1934 updatePerHalfedgeBuffers<&DrawMeshT::cachedNormalLookup>();
1935 else if (mesh_.is_trimesh())
1936 updatePerHalfedgeBuffers<&DrawMeshT::computedTriMeshNormal>();
1937 else
1938 updatePerHalfedgeBuffers<&DrawMeshT::computedNormal>();
1939 }
1940 return perHalfedgeColorBuf_.empty() ? 0 : &(perHalfedgeColorBuf_[0]);
1941}
1942
1943
1944
1945
1946template <class Mesh>
1948 unsigned int _offset)
1949{
1950 updatePerEdgeBuffers();
1951
1952 pickEdgeBuf_.resize(mesh_.n_edges() * 2);
1953
1954
1955 int idx = 0;
1956
1957 typename Mesh::ConstEdgeIter e_it(mesh_.edges_sbegin()), e_end(mesh_.edges_end());
1958 for (; e_it!=e_end; ++e_it) {
1959
1960 const Vec4uc pickColor = _state.pick_get_name_color (e_it->idx() + _offset);
1961
1962 pickEdgeBuf_[idx] = pickColor;
1963 pickEdgeBuf_[idx+1] = pickColor;
1964
1965 idx += 2;
1966 }
1967}
1968
1969
1970
1971template <class Mesh>
1973{
1974 // Make sure, the face buffers are up to date before generating the picking data!
1975 if (!numTris_ && mesh_.n_faces())
1976 {
1977 rebuild_ = REBUILD_FULL;
1978 rebuild();
1979 }
1980
1981 // nothing else to do, optimized edge picking method has no memory overhead
1982}
1983
1984
1985template <class Mesh>
1987{
1988 // fetch picking shader from cache (edge picking uses same shader as vertex picking)
1989 static ShaderGenDesc desc;
1990 desc.vertexTemplateFile = "Picking/vertex.glsl" ;
1991 desc.fragmentTemplateFile = "Picking/pick_vertices_fs2.glsl" ;
1992 pickEdgeShader_ = ShaderCache::getInstance()->getProgram(&desc, nullptr);
1993
1994 // check link status
1995 return pickEdgeShader_ && pickEdgeShader_->isLinked();
1996}
1997
1998
1999template <class Mesh>
2000void ACG::DrawMeshT<Mesh>::drawPickingEdges_opt( const GLMatrixf& _mvp, size_t _pickOffset )
2001{
2002 // optimized version which computes picking ids in the shader
2003
2004 /* optimization :
2005 - reuse draw vbo of drawmesh and line index buffer (which is used for wireframe mode)
2006 the line index buffer stores all edges in the same order as they appear in openmesh
2007 - use edge id of openmesh as gl_PrimitiveID in fragment shader to compute the picking id
2008
2009 -> no rendering from sysmem buffers
2010 -> no maintenance/update of picking colors required
2011 -> no additional memory allocation
2012 */
2013
2014 if (!numTris_)
2015 return;
2016
2017 // test support by loading and compiling picking shader
2018 if (!supportsPickingEdges_opt())
2019 return;
2020
2021 ACG::GLState::bindBufferARB(GL_ARRAY_BUFFER_ARB, getVBO());
2022 bindLineIbo();
2023
2024 // setup picking shader (same shader as in vertex picking)
2025 pickEdgeShader_->use();
2026 getVertexDeclaration()->activateShaderPipeline(pickEdgeShader_);
2027
2028 pickEdgeShader_->setUniform("pickVertexOffset", static_cast<GLint>(_pickOffset) );
2029 pickEdgeShader_->setUniform("mWVP", _mvp);
2030
2031 // draw call
2032 glDrawElements(GL_LINES, static_cast<GLsizei>(mesh_.n_edges() * 2), indexType_, 0);
2033
2034 // restore gl state
2035 getVertexDeclaration()->deactivateShaderPipeline(pickEdgeShader_);
2036 pickEdgeShader_->disable();
2037
2038 // unbind draw buffers
2039 ACG::GLState::bindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
2040 ACG::GLState::bindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
2041}
2042
2043
2044
2045
2046
2047
2048
2049
2050template <class Mesh>
2052{
2053 // Make sure, the face buffers are up to date before generating the picking data!
2054 if (!numTris_ && mesh_.n_faces())
2055 {
2056 rebuild_ = REBUILD_FULL;
2057 rebuild();
2058 }
2059
2060 pickFaceVertexBuf_.resize(3 * numTris_);
2061 pickFaceColBuf_.resize(3 * numTris_);
2062
2063 for (unsigned int i = 0; i < numTris_; ++i)
2064 {
2065 unsigned int faceId = (unsigned int)meshComp_->mapToOriginalFaceID((int)i);
2066
2067 const Vec4uc pickColor = _state.pick_get_name_color ( faceId );
2068 for (unsigned int k = 0; k < 3; ++k)
2069 {
2070 int idx = meshComp_->getIndex(i*3 + k);
2071
2072 typename Mesh::HalfedgeHandle hh = mapToHalfedgeHandle(idx);
2073 typename Mesh::VertexHandle vh;
2074
2075 if (hh.is_valid())
2076 vh = mesh_.to_vertex_handle( hh );
2077 else
2078 {
2079 int f_id, c_id;
2080 int posID = meshComp_->mapToOriginalVertexID(idx, f_id, c_id);
2081 vh = mesh_.vertex_handle(posID);
2082 }
2083
2084 pickFaceVertexBuf_[i * 3 + k] = mesh_.point( vh );
2085
2086 pickFaceColBuf_[i * 3 + k] = pickColor;
2087 }
2088 }
2089
2090
2091}
2092
2093
2094
2095template <class Mesh>
2097{
2098 // Make sure, the face buffers are up to date before generating the picking data!
2099 if (!numTris_ && mesh_.n_faces())
2100 {
2101 rebuild_ = REBUILD_FULL;
2102 rebuild();
2103 }
2104
2105 if (meshComp_ && meshComp_->getNumTriangles())
2106 {
2107 // upload tri->face lookup-table to texture buffer
2108 pickFaceTriToFaceMapTBO_.setBufferData(sizeof(int) * meshComp_->getNumTriangles(), meshComp_->mapToOriginalFaceIDPtr(), GL_R32I, GL_STATIC_DRAW);
2109 }
2110
2111}
2112
2113
2114template <class Mesh>
2116{
2117 if (!ACG::Texture::supportsTextureBuffer())
2118 return false;
2119
2120 // fetch picking shader from cache
2121 static ShaderGenDesc desc;
2122 desc.vertexTemplateFile = "Picking/vertex.glsl";
2123 desc.fragmentTemplateFile = "Picking/pick_face.glsl";
2124 pickFaceShader_ = ShaderCache::getInstance()->getProgram(&desc, nullptr);
2125
2126 // check link status
2127 return pickFaceShader_ && pickFaceShader_->isLinked();
2128}
2129
2130
2131template <class Mesh>
2132void ACG::DrawMeshT<Mesh>::drawPickingFaces_opt( const GLMatrixf& _mvp, size_t _pickOffset )
2133{
2134 // optimized version which computes picking ids in the shader
2135
2136 /* optimization idea:
2137 - reuse draw buffers of drawmesh
2138 - create lookup table which maps from draw triangle id to openmesh face id (stored in textureBuffer)
2139 - get base offset of face picking: pickFaceOffset = _state.pick_get_name_color(0)
2140 - render with following fragment shader, which computes face picking ids on the fly:
2141
2142 uniform int pickFaceOffset;
2143 uniform isamplerBuffer triangleToFaceMap;
2144
2145 out int outPickID; // if possible to write integer. otherwise, convert to ubyte4 or sth.
2146
2147 void main()
2148 {
2149 // map from triangle id to face id
2150 int faceID = texelFetch(triangleToFaceMap, gl_PrimitiveID);
2151
2152 outPickID = pickFaceOffset + faceID;
2153 // maybe the integer id has to be converted to a vec4 color here, not sure
2154 }
2155
2156 -> no rendering from sysmem buffers
2157 -> no maintenance/update of picking colors required
2158 -> lower memory footprint: 4 bytes per triangle
2159
2160 keep old approach to stay compatible on systems which do not support texture buffers or integer arithmetic in shaders
2161 */
2162
2163 if (!numTris_)
2164 return;
2165
2166 // test support by loading and compiling picking shader
2167 if (!supportsPickingFaces_opt())
2168 return;
2169
2170 // reuse cache optimized draw buffers
2171 ACG::GLState::bindBufferARB(GL_ARRAY_BUFFER_ARB, getVBO());
2172 ACG::GLState::bindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, getIBO());
2173
2174 // setup picking shader
2175 pickFaceShader_->use();
2176 getVertexDeclaration()->activateShaderPipeline(pickFaceShader_);
2177
2178 pickFaceShader_->setUniform("pickFaceOffset", static_cast<GLint>(_pickOffset));
2179 pickFaceShader_->setUniform("triToFaceMap", 0);
2180
2181 pickFaceTriangleMap_opt()->bind(GL_TEXTURE0);
2182
2183 pickFaceShader_->setUniform("mWVP", _mvp);
2184
2185 // draw call
2186 glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(getNumTris() * 3), getIndexType(), 0);
2187
2188 // restore gl state
2189 getVertexDeclaration()->deactivateShaderPipeline(pickFaceShader_);
2190 pickFaceShader_->disable();
2191
2192 // unbind draw buffers
2193 ACG::GLState::bindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
2194 ACG::GLState::bindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
2195}
2196
2197
2198
2199
2200template <class Mesh>
2202{
2203 if (!numTris_ && mesh_.n_faces())
2204 {
2205 rebuild_ = REBUILD_FULL;
2206 rebuild();
2207 }
2208
2209 pickFaceVertexBuf_.resize(3 * numTris_);
2210 pickAnyFaceColBuf_.resize(3 * numTris_);
2211
2212 for (unsigned int i = 0; i < numTris_; ++i)
2213 {
2214 int faceId = meshComp_->mapToOriginalFaceID(i);
2215 const Vec4uc pickColor = _state.pick_get_name_color ( faceId );
2216 for (unsigned int k = 0; k < 3; ++k)
2217 {
2218 int idx = meshComp_->getIndex(i*3 + k);
2219
2220
2221 typename Mesh::HalfedgeHandle hh = mapToHalfedgeHandle(idx);
2222 typename Mesh::VertexHandle vh;
2223
2224 if (hh.is_valid())
2225 vh = mesh_.to_vertex_handle( hh );
2226 else
2227 {
2228 int f_id, c_id;
2229 int posID = meshComp_->mapToOriginalVertexID(idx, f_id, c_id);
2230 vh = mesh_.vertex_handle(posID);
2231 }
2232
2233 pickFaceVertexBuf_[i * 3 + k] = mesh_.point( vh );
2234
2235 pickAnyFaceColBuf_[i * 3 + k] = pickColor;
2236 }
2237 }
2238
2239
2240
2241 updatePerEdgeBuffers();
2242
2243 pickAnyEdgeColBuf_.resize(mesh_.n_edges() * 2);
2244
2245 unsigned int idx = 0;
2246 typename Mesh::ConstEdgeIter e_it(mesh_.edges_sbegin()), e_end(mesh_.edges_end());
2247 for (; e_it!=e_end; ++e_it) {
2248
2249 const Vec4uc pickColor = _state.pick_get_name_color (e_it->idx() + mesh_.n_faces());
2250
2251 pickAnyEdgeColBuf_[idx] = pickColor;
2252 pickAnyEdgeColBuf_[idx+1] = pickColor;
2253
2254 idx += 2;
2255 }
2256
2257
2258
2259 idx = 0;
2260
2261 // Adjust size of the color buffer to the number of vertices in the mesh
2262 pickAnyVertexColBuf_.resize( mesh_.n_vertices() );
2263 pickVertBuf_.resize( mesh_.n_vertices() );
2264
2265 // Get the right picking colors from the gl state and add them per vertex to the color buffer
2266 typename Mesh::ConstVertexIter v_it(mesh_.vertices_begin()), v_end(mesh_.vertices_end());
2267 for (; v_it!=v_end; ++v_it, ++idx)
2268 {
2269 pickAnyVertexColBuf_[idx] = _state.pick_get_name_color(idx + mesh_.n_faces() + mesh_.n_edges());
2270 pickVertBuf_[idx] = mesh_.point(mesh_.vertex_handle(idx));
2271 }
2272}
2273
2274
2275
2276template <class Mesh>
2278{
2279 updatePickingFaces_opt(_state);
2280 updatePickingEdges_opt(_state);
2281 updatePickingVertices_opt(_state);
2282
2283 // optimized any picking does not require separate picking buffers
2284}
2285
2286template <class Mesh>
2288{
2289 return supportsPickingFaces_opt() && supportsPickingEdges_opt() && supportsPickingVertices_opt();
2290}
2291
2292
2293template <class Mesh>
2294void ACG::DrawMeshT<Mesh>::drawPickingAny_opt( const GLMatrixf& _mvp, size_t _pickOffset )
2295{
2296 // optimized version which computes picking ids in the shader
2297
2298 /* optimization:
2299 draw picking ids of faces, edges and vertices with appropriate offsets
2300 */
2301
2302 // test support by loading and compiling picking shader
2303 if (!supportsPickingAny_opt())
2304 return;
2305
2306 drawPickingFaces_opt(_mvp, _pickOffset);
2307
2308 ACG::GLState::depthFunc(GL_LEQUAL);
2309
2310 drawPickingEdges_opt(_mvp, _pickOffset + mesh_.n_faces());
2311
2312 drawPickingVertices_opt(_mvp, _pickOffset + mesh_.n_faces() + mesh_.n_edges());
2313}
2314
2315template <class Mesh>
2316void
2318setTextureIndexPropertyName( std::string _indexPropertyName ) {
2319
2320 // Check if the given property exists
2321 OpenMesh::FPropHandleT< int > textureIndexProperty;
2322 if ( !mesh_.get_property_handle(textureIndexProperty,_indexPropertyName) ) {
2323 if ( _indexPropertyName != "No Texture Index" )
2324 std::cerr << "DrawMeshT: Unable to get per face texture Index property named " << _indexPropertyName << std::endl;
2325 return;
2326 }
2327
2328 // Remember the property name
2329 textureIndexPropertyName_ = _indexPropertyName;
2330
2331 // mark strips as invalid ( have to be regenerated to collect texture index information)
2332// stripsValid_ = false;
2333//
2334// // mark the buffers as invalid as we have a new per face index array
2335// invalidatePerFaceBuffers();
2336 rebuild_ |= REBUILD_TOPOLOGY;
2337}
2338
2339template <class Mesh>
2340void
2342setPerFaceTextureCoordinatePropertyName( std::string _perFaceTextureCoordinatePropertyName ) {
2343
2344 // Check if the given property exists
2345 OpenMesh::HPropHandleT< typename Mesh::TexCoord2D > perFaceTextureCoordinateProperty;
2346 if ( !mesh_.get_property_handle(perFaceTextureCoordinateProperty,_perFaceTextureCoordinatePropertyName) ) {
2347 if ( _perFaceTextureCoordinatePropertyName != "No Texture" )
2348 std::cerr << "DrawMeshT: Unable to get per face texture coordinate property named " << _perFaceTextureCoordinatePropertyName << std::endl;
2349 return;
2350 }
2351
2352 // Remember the property name
2353 perFaceTextureCoordinatePropertyName_ = _perFaceTextureCoordinatePropertyName;
2354
2355 // mark the buffers as invalid as we have a new per face index array
2356// invalidatePerFaceBuffers();
2357 rebuild_ |= REBUILD_GEOMETRY;
2358}
2359
2360
2361template <class Mesh>
2363{
2364 unsigned int n = 0;
2365 for (int i = 0; i < meshComp_->getNumSubsets(); ++i)
2366 {
2367 if (meshComp_->getSubset(i)->id > 0) ++n;
2368 }
2369 return n;
2370}
2371
2372template <class Mesh>
2373int
2375
2376 // We really have to recheck, as the property might get lost externally (e.g. on restores of the mesh)
2377 OpenMesh::HPropHandleT< typename Mesh::TexCoord2D > perFaceTextureCoordinateProperty;
2378 if ( !mesh_.get_property_handle(perFaceTextureCoordinateProperty, perFaceTextureCoordinatePropertyName_) ) {
2379 return false;
2380 }
2381
2382 // Property available
2383 return true;
2384
2385}
2386
2387
2388template <class Mesh>
2389int
2391
2392 // We really have to recheck, as the property might get lost externally (e.g. on restores of the mesh)
2393 OpenMesh::FPropHandleT< int > textureIndexProperty;
2394 if ( !mesh_.get_property_handle(textureIndexProperty, textureIndexPropertyName_) ) {
2395 return false;
2396 }
2397
2398 // Property available
2399 return true;
2400}
2401
2402
2403
2404
2405
2406
2407template <class Mesh>
2409{
2410 vertexDecl_->clear();
2411
2412 vertexDecl_->addElement(GL_FLOAT, 3, VERTEX_USAGE_POSITION);
2413 vertexDecl_->addElement(GL_FLOAT, 2, VERTEX_USAGE_TEXCOORD);
2414 vertexDecl_->addElement(GL_FLOAT, 3, VERTEX_USAGE_NORMAL);
2415 vertexDecl_->addElement(GL_UNSIGNED_BYTE, 4, VERTEX_USAGE_COLOR);
2416
2417 for (size_t i = 0; i < additionalElements_.size(); ++i)
2418 {
2419 VertexProperty* prop = &additionalElements_[i];
2420
2421 // invalidate detected type
2422 prop->sourceType_.numElements_ = 0;
2423 prop->sourceType_.pointer_ = 0;
2424 prop->sourceType_.type_ = 0;
2425 prop->sourceType_.shaderInputName_ = 0;
2427 prop->propDataPtr_ = 0;
2428 prop->declElementID_ = -1;
2429
2430 // get property handle in openmesh by name
2431 OpenMesh::BaseProperty* baseProp = 0;
2432
2433 switch (prop->source_)
2434 {
2435 case PROPERTY_SOURCE_VERTEX: baseProp = mesh_._get_vprop(prop->name_); break;
2436 case PROPERTY_SOURCE_FACE: baseProp = mesh_._get_fprop(prop->name_); break;
2437 case PROPERTY_SOURCE_HALFEDGE: baseProp = mesh_._get_hprop(prop->name_); break;
2438 default: baseProp = mesh_._get_vprop(prop->name_); break;
2439 }
2440
2441 // detect data type of property
2442 prop->propDataPtr_ = getMeshPropertyType(baseProp, &prop->sourceType_.type_, &prop->sourceType_.numElements_);
2443
2444
2445 if (prop->propDataPtr_)
2446 {
2447 prop->sourceType_.shaderInputName_ = prop->name_.c_str();
2448
2449 // should have same type in vbo
2450 prop->destType_ = prop->sourceType_;
2451
2453
2454 prop->declElementID_ = int(vertexDecl_->getNumElements());
2455
2456 vertexDecl_->addElement(&prop->destType_);
2457 }
2458 else
2459 std::cerr << "Could not detect data type of property " << prop->name_ << std::endl;
2460 }
2461}
2462
2463
2464template <class Mesh>
2466{
2467 vertexDeclEdgeCol_->clear();
2468 vertexDeclEdgeCol_->addElement(GL_FLOAT, 3, VERTEX_USAGE_POSITION, perEdgeVertexBuffer());
2469 vertexDeclEdgeCol_->addElement(GL_FLOAT, 4, VERTEX_USAGE_COLOR, perEdgeColorBuffer());
2470
2471 vertexDeclHalfedgeCol_->clear();
2472 vertexDeclHalfedgeCol_->addElement(GL_FLOAT, 3, VERTEX_USAGE_POSITION, perHalfedgeVertexBuffer());
2473 vertexDeclHalfedgeCol_->addElement(GL_FLOAT, 4, VERTEX_USAGE_COLOR, perHalfedgeColorBuffer());
2474
2475 vertexDeclHalfedgePos_->clear();
2476 vertexDeclHalfedgePos_->addElement(GL_FLOAT, 3, VERTEX_USAGE_POSITION, perHalfedgeVertexBuffer());
2477
2478 vertexDeclEdgeCol_->setVertexStride(0);
2479 vertexDeclHalfedgeCol_->setVertexStride(0);
2480 vertexDeclHalfedgePos_->setVertexStride(0);
2481}
2482
2483template <class Mesh>
2488
2489
2490template<class Mesh>
2492{
2493 int faceId = -1, cornerId = -1;
2494
2495 // map to halfedge handle
2496 if (meshComp_)
2497 meshComp_->mapToOriginalVertexID(_vertexId, faceId, cornerId);
2498
2499 if (faceId >= 0)
2500 {
2501 typename Mesh::FaceHandle fh = mesh_.face_handle(faceId);
2502 typename Mesh::FaceHalfedgeIter hh_it = mesh_.fh_iter(fh);
2503
2504 // seek to halfedge
2505 for (int k = 0; k < cornerId && hh_it.is_valid(); ++k )
2506 ++hh_it;
2507
2508 return *hh_it;
2509 }
2510 else
2511 return typename Mesh::HalfedgeHandle(-1);
2512}
2513
2514
2515template <class Mesh>
2516void ACG::DrawMeshT<Mesh>::writeVertexElement( void* _dstBuf, size_t _vertex, size_t _stride, size_t _elementOffset, size_t _elementSize, const void* _elementData )
2517{
2518 // byte offset
2519 size_t offset = _vertex * _stride + _elementOffset;
2520
2521 // write address
2522 char* dst = static_cast<char*>(_dstBuf) + offset;
2523
2524 // copy
2525 memcpy(dst, _elementData, _elementSize);
2526}
2527
2528template <class Mesh>
2529void ACG::DrawMeshT<Mesh>::writePosition( size_t _vertex, const ACG::Vec3d& _n )
2530{
2531 // store float3 position
2532 float f3[3] = {float(_n[0]), float(_n[1]), float(_n[2])};
2533
2534 writeVertexElement(&vertices_[0], _vertex, vertexDecl_->getVertexStride(), 0, 12, f3);
2535}
2536
2537template <class Mesh>
2538void ACG::DrawMeshT<Mesh>::writeNormal( size_t _vertex, const ACG::Vec3d& _n )
2539{
2540 // store float3 normal
2541 float f3[3] = {float(_n[0]), float(_n[1]), float(_n[2])};
2542
2543 writeVertexElement(&vertices_[0], _vertex, vertexDecl_->getVertexStride(), offsetNormal_, 12, f3);
2544}
2545
2546
2547template <class Mesh>
2548void ACG::DrawMeshT<Mesh>::writeTexcoord( size_t _vertex, const ACG::Vec2f& _uv )
2549{
2550 writeVertexElement(&vertices_[0], _vertex, vertexDecl_->getVertexStride(), offsetTexc_, 8, _uv.data());
2551}
2552
2553template <class Mesh>
2554void ACG::DrawMeshT<Mesh>::writeColor( size_t _vertex, unsigned int _color )
2555{
2556 writeVertexElement(&vertices_[0], _vertex, vertexDecl_->getVertexStride(), offsetColor_, 4, &_color);
2557}
2558
2559
2560template <class Mesh>
2561void ACG::DrawMeshT<Mesh>::writeVertexProperty( size_t _vertex, const VertexElement* _elementDesc, const ACG::Vec4f& _propf )
2562{
2563 const size_t elementSize = VertexDeclaration::getElementSize(_elementDesc);
2564
2565 writeVertexElement(&vertices_[0], _vertex, vertexDecl_->getVertexStride(), _elementDesc->getByteOffset(), elementSize, _propf.data());
2566}
2567
2568
2569
2570template <class Mesh>
2571void ACG::DrawMeshT<Mesh>::addVertexElement( const std::string& _propertyName, PropertySource _source )
2572{
2573 // check if element has already been requested before
2574
2575 for (size_t i = 0; i < additionalElements_.size(); ++i)
2576 {
2577 if (additionalElements_[i].name_ == _propertyName)
2578 {
2579 additionalElements_[i].source_ = _source;
2580
2581 return;
2582 }
2583 }
2584
2585
2586 // request new property
2587 VertexProperty prop;
2588
2589 prop.name_ = _propertyName;
2590 prop.source_ = _source;
2591 prop.vertexShaderInputName_ = _propertyName;
2592 // rest of property desc is initialized later in createVertexDeclaration()
2593
2594 additionalElements_.push_back(prop);
2595
2596 updateFull();
2597}
2598
2599
2600template <class Mesh>
2601bool ACG::DrawMeshT<Mesh>::scanVertexShaderForInput( const std::string& _vertexShaderFile )
2602{
2603 bool success = true;
2604
2605 std::ifstream file;
2606
2607 file.open(_vertexShaderFile.c_str(), std::ios_base::in);
2608
2609 if (file.is_open())
2610 {
2611 while (!file.eof())
2612 {
2613 char line[0xff];
2614
2615 file.getline(line, 0xff);
2616
2617 // get rid of whitespaces at begin/end, and internal padding
2618 QString strLine = line;
2619 strLine = strLine.simplified();
2620
2621 // pattern matching for vertex input attributes
2622 if (!strLine.startsWith("//") && !strLine.startsWith("*/"))
2623 {
2624
2625 if (strLine.startsWith("in ") || strLine.contains(" in "))
2626 {
2627 // extract
2628 int semIdx = strLine.indexOf(';');
2629
2630
2631 if (semIdx >= 0)
2632 {
2633 // property name = string before semicolon without whitespace
2634
2635 // remove parts after semicolon
2636 QString strName = strLine;
2637 strName.remove(semIdx, strName.length());
2638
2639 strName = strName.simplified();
2640
2641 // property name = string between last whitespace and last character
2642 int lastWhite = strName.lastIndexOf(' ');
2643
2644 if (lastWhite >= 0)
2645 {
2646 strName.remove(0, lastWhite);
2647
2648 strName = strName.simplified();
2649
2650 // check for reserved input attributes
2651 if (strName != "inPosition" &&
2652 strName != "inTexCoord" &&
2653 strName != "inNormal" &&
2654 strName != "inColor")
2655 {
2656 // custom property
2657
2658 std::string propName = strName.toStdString();
2659
2660 // choose property source
2661 PropertySource src = PROPERTY_SOURCE_VERTEX;
2662
2663 if (strLine.contains("flat "))
2664 {
2665 // per face attribute
2666 src = PROPERTY_SOURCE_FACE;
2667
2668 if (!mesh_._get_fprop(propName))
2669 src = PROPERTY_SOURCE_VERTEX; // face source not available, try vertex next..
2670 }
2671
2672 if (src == PROPERTY_SOURCE_VERTEX)
2673 {
2674 if (!mesh_._get_vprop(propName))
2675 src = PROPERTY_SOURCE_HALFEDGE; // vertex source not available, try halfedge next..
2676 }
2677
2678 // prefer halfedge props over vertex props
2679 if (src == PROPERTY_SOURCE_VERTEX)
2680 {
2681 if ( mesh_._get_hprop(propName) && src == PROPERTY_SOURCE_VERTEX)
2682 src = PROPERTY_SOURCE_HALFEDGE;
2683 }
2684
2685 // error output if property does not exist
2686 if (src == PROPERTY_SOURCE_HALFEDGE && !mesh_._get_hprop(propName))
2687 {
2688 std::cerr << "DrawMesh error - requested property " << propName << " does not exist" << std::endl;
2689 success = false;
2690 }
2691 else
2692 {
2693 addVertexElement(propName, src);
2694 }
2695
2696 }
2697
2698 }
2699 }
2700
2701
2702 }
2703
2704 }
2705
2706 }
2707
2708
2709 }
2710
2711 return success;
2712}
2713
2714template<class Mesh>
2715void DrawMeshT<Mesh>::dumpObj(const char* _filename) const
2716{
2717 std::ofstream file;
2718 file.open(_filename);
2719
2720 if (file.is_open())
2721 {
2722 for (int attrId = 0; attrId < 3; ++attrId)
2723 {
2724 for ( size_t i = 0; i < numVerts_; ++i)
2725 {
2726 // ptr to vertex
2727 const char* v = &vertices_[i * vertexDecl_->getVertexStride()];
2728
2729 const float* pos = reinterpret_cast<const float*>((const void*)(v + offsetPos_));
2730 const float* n = reinterpret_cast<const float*>((const void*)(v + offsetNormal_));
2731 const float* texc = reinterpret_cast<const float*>((const void*)(v + offsetTexc_));
2732// unsigned int col = *reinterpret_cast<const unsigned int*>(v + offsetColor_);
2733
2734 switch (attrId)
2735 {
2736 case 0: file << "v "<<pos[0]<<" "<<pos[1]<<" "<<pos[2]<<"\n"; break;
2737 case 1: file << "vt "<<texc[0]<<" "<<texc[1]<<"\n"; break;
2738 case 2: file << "vn "<<n[0]<<" "<<n[1]<<" "<<n[2]<<"\n"; break;
2739 default: break;
2740 }
2741 }
2742 }
2743
2744
2745 for (size_t i = 0; i < numTris_; ++i)
2746 {
2747 // ptr to triangle
2748 const int* tri = meshComp_->getIndexBuffer() + i*3;
2749
2750 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";
2751 }
2752
2753 file.close();
2754 }
2755}
2756
2757
2758
2759template <class Mesh>
2760void ACG::DrawMeshT<Mesh>::readVertexFromVBO(unsigned int _vertex, void* _dst)
2761{
2762 assert(_dst != 0);
2763
2764 unsigned int stride = vertexDecl_->getVertexStride();
2765
2766 // byte offset
2767 unsigned int offset = _vertex * stride;
2768
2769 // copy
2770 memcpy(_dst, &vertices_[offset], stride);
2771}
2772
2773
2774
2775
2776
2777template <class Mesh>
2779{
2780 updateFullVBO_ = true;
2781}
2782
2783
2784template <class Mesh>
2786{
2787 // update indexed vbo first, in the next step this vbo is resolved into non-indexed
2788 updateGPUBuffers();
2789
2790 if (updateFullVBO_)
2791 {
2792 MeshCompiler* mc = getMeshCompiler();
2793
2794 if (mc)
2795 {
2796 int numTris = mc->getNumTriangles();
2797
2798 // alloc buffer
2799 int numVerts = 3 * numTris;
2800 int stride = mc->getVertexDeclaration()->getVertexStride();
2801 std::vector<char> fullBuf(numVerts * stride);
2802
2803 // fill buffer
2804 for (int i = 0; i < numTris; ++i)
2805 {
2806 for (int k = 0; k < 3; ++k)
2807 {
2808 int idx = i * 3 + k;
2809 int vertexID = mc->getIndex(idx);
2810 readVertexFromVBO(vertexID, &fullBuf[idx * stride]);
2811
2812 if (colorMode_ == 2)
2813 {
2814 // read face color
2815
2816 int faceId = meshComp_->mapToOriginalFaceID(i);
2817 unsigned int fcolor = getFaceColor(mesh_.face_handle(faceId));
2818
2819 // store face color
2820 writeVertexElement(&fullBuf[0], idx, vertexDecl_->getVertexStride(), offsetColor_, 4, &fcolor);
2821 }
2822
2823 }
2824 }
2825
2826 if (!fullBuf.empty())
2827 vboFull_.upload(fullBuf.size(), &fullBuf[0], GL_STATIC_DRAW);
2828
2829 // clean update flag
2830 updateFullVBO_ = false;
2831 }
2832 }
2833}
2834} // namespace ACG
int getSingleFaceAttr(const int _faceID, const int _faceCorner, const int _attrID) const
int getVertexAdjFace(const int _vertexID, const int _k) const
int * getFaceAttr(const int _faceID, const int _attrID) const
int getVertexAdjCount(const int _vertexID) const
bool getFaceAttr(const int _faceID, const int _attrID, int *_out) const
Mesh Drawing Class.
Definition DrawMesh.hh:172
VertexDeclaration * getVertexDeclaration()
get vertex declaration of the current vbo layout
void createVertexDeclaration()
creates all vertex declarations needed for deferred draw call renderer
void drawPickingFaces_opt(const GLMatrixf &_mvp, size_t _pickOffset)
Optimized rendering of face picking ids with a shader.
void drawPickingEdges_opt(const GLMatrixf &_mvp, size_t _pickOffset)
Optimized rendering of edge picking ids with a shader.
void drawPickingAny_opt(const GLMatrixf &_mvp, size_t _pickOffset)
Optimized rendering of any picking ids with a shader.
void addVertexElement(const std::string &_propertyName, PropertySource _source=PROPERTY_SOURCE_VERTEX)
Add custom elements to the vertex layout.
unsigned int getMemoryUsage(bool _printReport=false)
measures the size in bytes of allocated memory. eventually prints a report to std::cout
void invalidateFullVBO()
the mesh has been changed
bool supportsPickingAny_opt()
Check if optimized any picking is supported.
bool supportsPickingVertices_opt()
Check if optimized vertex picking is supported.
void readVertexFromVBO(unsigned int _vertex, void *_dst)
Read one vertex from the rendering vbo.
bool supportsPickingEdges_opt()
Check if optimized face picking is supported.
bool supportsPickingFaces_opt()
Check if optimized face picking is supported.
void addTriRenderObjects(IRenderer *_renderer, const RenderObject *_baseObj, std::map< int, GLuint > *_textureMap, bool _nonindexed=false)
adds RenderObjects to a deferred draw call renderer
void updateFullVBO()
update the full mesh vbo
void drawPickingVertices_opt(const GLMatrixf &_mvp, size_t _pickOffset)
Optimized rendering of vertex picking ids with a shader.
bool scanVertexShaderForInput(const std::string &_vertexShaderFile)
Scan vertex layout from vertex shader.
void updateEdgeHalfedgeVertexDeclarations()
updates per edge and halfedge vertex declarations
static void disableClientState(GLenum _cap)
replaces glDisableClientState, supports locking
Definition GLState.cc:1584
static void colorPointer(GLint _size, GLenum _type, GLsizei _stride, const GLvoid *_pointer)
replaces glColorPointer, supports locking
Definition GLState.cc:2005
static void vertexPointer(GLint _size, GLenum _type, GLsizei _stride, const GLvoid *_pointer)
replaces glVertexPointer, supports locking
Definition GLState.cc:1961
Vec4uc pick_get_name_color(size_t _idx)
Definition GLState.cc:1068
static void bindBufferARB(GLenum _target, GLuint _buffer)
same function as bindBuffer
Definition GLState.hh:579
static void bindTexture(GLenum _target, GLuint _buffer)
replaces glBindTexture, supports locking
Definition GLState.cc:1911
static void normalPointer(GLenum _type, GLsizei _stride, const GLvoid *_pointer)
replaces glNormalPointer, supports locking
Definition GLState.cc:1983
static void enableClientState(GLenum _cap)
replaces glEnableClientState, supports locking
Definition GLState.cc:1570
static void texcoordPointer(GLint _size, GLenum _type, GLsizei _stride, const GLvoid *_pointer)
replaces glTexcoordPointer, supports locking
Definition GLState.cc:2027
const GLenum & depthFunc() const
get glDepthFunc() that is supposed to be active
Definition GLState.cc:941
static void bindBuffer(GLenum _target, GLuint _buffer)
replaces glBindBuffer, supports locking
Definition GLState.cc:1820
virtual void addRenderObject(RenderObject *_renderObject)
Callback for the scenegraph nodes, which send new render objects via this function.
Definition IRenderer.cc:104
int getNumTriangles() const
int getIndex(int _i) const
const VertexDeclaration * getVertexDeclaration() const
Class to define the vertex input layout.
unsigned int getVertexStride(unsigned int i=0) const
virtual size_t n_elements() const =0
Number of elements in property.
Kernel::VertexHandle VertexHandle
Handle for referencing the corresponding item.
Definition PolyMeshT.hh:136
Kernel::ConstFaceHalfedgeIter ConstFaceHalfedgeIter
Circulator.
Definition PolyMeshT.hh:178
Kernel::ConstVertexFaceIter ConstVertexFaceIter
Circulator.
Definition PolyMeshT.hh:176
Kernel::ConstHalfedgeIter ConstHalfedgeIter
Scalar type.
Definition PolyMeshT.hh:149
Kernel::FaceHandle FaceHandle
Scalar type.
Definition PolyMeshT.hh:139
Kernel::HalfedgeHandle HalfedgeHandle
Scalar type.
Definition PolyMeshT.hh:137
Kernel::ConstEdgeIter ConstEdgeIter
Scalar type.
Definition PolyMeshT.hh:150
Kernel::ConstVertexIter ConstVertexIter
Scalar type.
Definition PolyMeshT.hh:148
Kernel::FaceHalfedgeIter FaceHalfedgeIter
Circulator.
Definition PolyMeshT.hh:168
Kernel::Point Point
Coordinate type.
Definition PolyMeshT.hh:112
Default property class for any type T.
Definition Property.hh:93
const T * data() const
Get pointer to array (does not work for T==bool)
Definition Property.hh:176
Scalar * data()
access to Scalar array
Definition Vector11T.hh:201
Namespace providing different geometric functions concerning angles.
bool ACGDLLEXPORT openGLVersionTest(const int _major, const int _minor)
Definition gl.hh:275
VectorT< float, 3 > Vec3f
Definition VectorT.hh:119
@ VERTEX_USAGE_NORMAL
"inNormal"
@ VERTEX_USAGE_COLOR
"inColor"
@ VERTEX_USAGE_POSITION
"inPosition"
@ VERTEX_USAGE_TEXCOORD
"inTexCoord"
@ VERTEX_USAGE_SHADER_INPUT
defined by user via VertexElement::shaderInputName_
VectorT< unsigned char, 4 > Vec4uc
Definition VectorT.hh:128
const void * propDataPtr_
memory address of property data
Definition DrawMesh.hh:888
VertexElement sourceType_
property type as stored in openmesh
Definition DrawMesh.hh:882
std::string vertexShaderInputName_
input name id in vertex shader
Definition DrawMesh.hh:879
VertexElement destType_
property type as stored in vbo
Definition DrawMesh.hh:885
std::string name_
property name in openmesh
Definition DrawMesh.hh:876
int declElementID_
element id in vertex declaration
Definition DrawMesh.hh:891
Texture to be used.
Interface class between scenegraph and renderer.
ShaderGenDesc shaderDesc
Drawmode and other shader params.
const VertexDeclaration * vertexDecl
Defines the vertex buffer layout, ignored if VAO is provided.
void addTexture(const Texture &_t)
adds a texture to stage RenderObjects::numTextures()
GLuint indexBuffer
Use vertex array object.
GLuint vertexBuffer
VBO, IBO ids, ignored if VAO is provided.
GLenum indexType
Index element type.
Description of one vertex element.
unsigned int numElements_
how many elements of type_
const void * pointer_
Offset in bytes to the first occurrence of this element in vertex buffer; Or address to vertex data i...
VERTEX_USAGE usage_
position, normal, shader input ..
unsigned int type_
GL_FLOAT, GL_UNSIGNED_BYTE, GL_INT, ...
const char * shaderInputName_
set shader input name, if usage_ = VERTEX_USAGE_USER_DEFINED otherwise this is set automatically,...
Handle for a halfedge entity.
Definition Handles.hh:128