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
VolumeMeshBufferManagerT.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 VOLUMEMESHBUFFERMANAGERT_CC
51
52 #include "VolumeMeshBufferManager.hh"
53
54 template <class VolumeMesh>
55 VolumeMeshBufferManager<VolumeMesh>::VolumeMeshBufferManager(const VolumeMesh &mesh_, OpenVolumeMesh::StatusAttrib& statusAttrib_,
56 OpenVolumeMesh::ColorAttrib<ACG::Vec4f>& colorAttrib_,
57 OpenVolumeMesh::NormalAttrib<VolumeMesh>& normalAttrib_,
58 OpenVolumeMesh::TexCoordAttrib<ACG::Vec2f>& texcoordAttrib_)
59 :
60 mDefaultColor(ACG::Vec4f(0.0,0.0,0.0,1.0)),
61 mMesh(mesh_),
62 mStatusAttrib(statusAttrib_),
63 mColorAttrib(colorAttrib_),
64 mNormalAttrib(normalAttrib_),
65 mTexcoordAttrib(texcoordAttrib_),
66 mNumOfVertices(-1),
67 mCurrentNumOfVertices(-1),
68 mVertexSize(0),
69 mVertexDeclaration(),
70 mColorOffset(-1),
71 mNormalOffset(-1),
72 mScale(0.8),
73 mBuffer(0),
74 mCurrentPickOffset(-1),
75 mGlobalPickOffset(0),
76 mInvalidated(true),
77 mGeometryChanged(true),
78 mNormalsChanged(true),
79 mColorsChanged(true),
80 mTexCoordsChanged(true),
81 mDrawModes(),
82 mPrimitiveMode(PM_NONE),
83 mNormalMode(NM_NONE),
84 mColorMode(CM_NO_COLORS),
85 mSkipUnselected(false),
86 mShowIrregularInnerEdges(false),
87 mShowIrregularOuterValence2Edges(false),
88 mSkipRegularEdges(false),
89 mBoundaryOnly(false),
90 mCurrentPrimitiveMode(PM_NONE),
91 mCurrentNormalMode(NM_NONE),
92 mCurrentColorMode(CM_NO_COLORS),
93 mCurrentSkipUnselected(false),
94 mCurrentShowIrregularInnerEdges(false),
95 mCurrentShowIrregularOuterValence2Edges(false),
96 mCurrentSkipRegularEdges(false),
97 mCurrentBoundaryOnly(false),
98 mCurrentVertexSize(0),
99 mCurrentNormalOffset(0),
100 mCurrentColorOffset(0),
101 mCogsValid(false),
102 mCellInsidenessValid(),
103 mTexCoordMode(TCM_NONE),
104 mCurrentTexCoordMode(TCM_NONE),
105 mTexCoordOffset(0),
106 mCurrentTexCoordOffset(0)
107 {
108
109 }
110
120 template <class VolumeMesh>
121 void VolumeMeshBufferManager<VolumeMesh>::addFloatToBuffer( float _value, unsigned char *&_buffer )
122 {
123 // get pointer
124 unsigned char *v = (unsigned char *) &_value;
125
126 // copy over 4 bytes
127 *_buffer++ = *v++;
128 *_buffer++ = *v++;
129 *_buffer++ = *v++;
130 *_buffer++ = *v;
131 }
132
142 template <class VolumeMesh>
143 void VolumeMeshBufferManager<VolumeMesh>::addUCharToBuffer( unsigned char _value, unsigned char *&_buffer )
144 {
145 *_buffer = _value;
146 ++_buffer;
147 }
148
159 template <class VolumeMesh>
160 void VolumeMeshBufferManager<VolumeMesh>::addPositionToBuffer(ACG::Vec3d _position, unsigned char* _buffer , unsigned int _offset)
161 {
162 unsigned char* buffer = _buffer + _offset*mVertexSize;
163 addFloatToBuffer(_position[0], buffer);
164 addFloatToBuffer(_position[1], buffer);
165 addFloatToBuffer(_position[2], buffer);
166 }
167
178 template <class VolumeMesh>
179 void VolumeMeshBufferManager<VolumeMesh>::addColorToBuffer(ACG::Vec4uc _color, unsigned char* _buffer, unsigned int _offset)
180 {
181 unsigned char* buffer = _buffer + _offset*mVertexSize + mColorOffset;
182 addUCharToBuffer(_color[0], buffer);
183 addUCharToBuffer(_color[1], buffer);
184 addUCharToBuffer(_color[2], buffer);
185 addUCharToBuffer(_color[3], buffer);
186 }
187
200 template <class VolumeMesh>
201 void VolumeMeshBufferManager<VolumeMesh>::addColorToBuffer(ACG::Vec4f _color, unsigned char* _buffer, unsigned int _offset)
202 {
203 unsigned char* buffer = _buffer + _offset*mVertexSize + mColorOffset;
204 addUCharToBuffer(_color[0]*255, buffer);
205 addUCharToBuffer(_color[1]*255, buffer);
206 addUCharToBuffer(_color[2]*255, buffer);
207 addUCharToBuffer(_color[3]*255, buffer);
208 }
209
220 template <class VolumeMesh>
221 void VolumeMeshBufferManager<VolumeMesh>::addNormalToBuffer(ACG::Vec3d _normal, unsigned char* _buffer, unsigned int _offset)
222 {
223 unsigned char* buffer = _buffer + _offset*mVertexSize + mNormalOffset;
224 addFloatToBuffer(_normal[0], buffer);
225 addFloatToBuffer(_normal[1], buffer);
226 addFloatToBuffer(_normal[2], buffer);
227 }
228
239 template <class VolumeMesh>
240 void VolumeMeshBufferManager<VolumeMesh>::addTexCoordToBuffer(ACG::Vec2f _texCoord, unsigned char* _buffer, unsigned int _offset)
241 {
242 unsigned char* buffer = _buffer + _offset*mVertexSize + mTexCoordOffset;
243 addFloatToBuffer(_texCoord[0], buffer);
244 addFloatToBuffer(_texCoord[1], buffer);
245 }
246
247
255 template <class VolumeMesh>
256 void VolumeMeshBufferManager<VolumeMesh>::calculateVertexDeclaration()
257 {
258 unsigned int currentOffset = 0;
259 mVertexDeclaration.clear();
260
261 mNormalOffset = -1;
262 mColorOffset = -1;
263
264 if (mPrimitiveMode != PM_NONE) //should always be the case
265 {
266 mVertexDeclaration.addElement(GL_FLOAT, 3, ACG::VERTEX_USAGE_POSITION, reinterpret_cast<GLuint*>(currentOffset));
267 currentOffset += 3*sizeof(float);
268 }
269
270 if (mNormalMode != NM_NONE)
271 {
272 mNormalOffset = currentOffset;
273 mVertexDeclaration.addElement(GL_FLOAT, 3, ACG::VERTEX_USAGE_NORMAL, reinterpret_cast<GLuint*>(currentOffset));
274 currentOffset += 3*sizeof(float);
275 }
276
277 if ((mColorMode != CM_NO_COLORS) || mShowIrregularInnerEdges || mShowIrregularOuterValence2Edges)
278 {
279 mColorOffset = currentOffset;
280 mVertexDeclaration.addElement(GL_UNSIGNED_BYTE, 4, ACG::VERTEX_USAGE_COLOR, reinterpret_cast<GLuint*>(currentOffset));
281 currentOffset += 4*sizeof(char);
282 }
283
284 if ((mTexCoordMode != TCM_NONE))
285 {
286 mTexCoordOffset = currentOffset;
287 unsigned char numOfCoords = 0;
288 if (mTexCoordMode == TCM_SINGLE_2D)
289 numOfCoords = 2;
290 mVertexDeclaration.addElement(GL_FLOAT, numOfCoords, ACG::VERTEX_USAGE_TEXCOORD, reinterpret_cast<GLuint*>(currentOffset));
291 currentOffset += numOfCoords * sizeof(float);
292 }
293
294 mVertexSize = currentOffset;
295 }
296
297
302 template <class VolumeMesh>
303 unsigned int VolumeMeshBufferManager<VolumeMesh>::getNumOfVertices()
304 {
305 if (mNumOfVertices == -1)
306 countNumOfVertices();
307 return mNumOfVertices;
308 }
309
317 template <class VolumeMesh>
318 void VolumeMeshBufferManager<VolumeMesh>::setDefaultColor(ACG::Vec4f _defaultColor)
319 {
320 if (mDefaultColor != _defaultColor)
321 {
322 invalidateColors();
323 mDefaultColor = _defaultColor;
324 }
325 }
326
335 template <class VolumeMesh>
336 void VolumeMeshBufferManager<VolumeMesh>::setOptionsFromDrawMode(ACG::SceneGraph::DrawModes::DrawMode _drawMode)
337 {
338 // colors
339 if (_drawMode & (mDrawModes.cellsColoredPerCell))
340 enablePerCellColors();
341 else if (_drawMode & (mDrawModes.cellsColoredPerFace | mDrawModes.facesColoredPerFace))
342 enablePerFaceColors();
343 else if (_drawMode & (mDrawModes.cellsColoredPerHalfface | mDrawModes.halffacesColoredPerHalfface))
344 enablePerHalffaceColors();
345 else if (_drawMode & ( mDrawModes.edgesColoredPerEdge ))
346 enablePerEdgeColors();
347 else if (_drawMode & (mDrawModes.halfedgesColoredPerHalfedge))
348 enablePerHalfedgeColors();
349 else if (_drawMode & (mDrawModes.cellsColoredPerVertex | mDrawModes.facesColoredPerVertex |
350 mDrawModes.halffacesColoredPerVertex | mDrawModes.edgesColoredPerEdge |
351 mDrawModes.verticesColored))
352 enablePerVertexColors();
353 else
354 disableColors();
355
356 //normals
357 if (_drawMode & (mDrawModes.cellsFlatShaded | mDrawModes.halffacesFlatShaded))
358 enablePerHalffaceNormals();
359 else if (_drawMode & (mDrawModes.facesFlatShaded | mDrawModes.facesTexturedShaded))
360 enablePerFaceNormals();
361 else if (_drawMode & (mDrawModes.cellsSmoothShaded | mDrawModes.facesSmoothShaded | mDrawModes.halffacesSmoothShaded |
362 mDrawModes.cellsPhongShaded | mDrawModes.facesPhongShaded | mDrawModes.halffacesPhongShaded))
363 enablePerVertexNormals();
364 else
365 disableNormals();
366
367 if (_drawMode & (mDrawModes.irregularInnerEdges))
368 mShowIrregularInnerEdges = true;
369 else
370 mShowIrregularInnerEdges = false;
371
372 if (_drawMode & (mDrawModes.irregularOuterEdges))
373 mShowIrregularOuterValence2Edges = true;
374 else
375 mShowIrregularOuterValence2Edges = false;
376
377 if (!mShowIrregularInnerEdges && !mShowIrregularOuterValence2Edges)
378 mSkipRegularEdges = false;
379 else
380 mSkipRegularEdges = true;
381
382
383 // textures
384 if (_drawMode & (mDrawModes.facesTextured | mDrawModes.facesTexturedShaded))
385 mTexCoordMode = TCM_SINGLE_2D;
386 else
387 mTexCoordMode = TCM_NONE;
388
389 // primiive mode
390 if (_drawMode & (mDrawModes.cellBasedDrawModes))
391 mPrimitiveMode = PM_CELLS;
392 else if (_drawMode & (mDrawModes.facesOnCells))
393 mPrimitiveMode = PM_FACES_ON_CELLS;
394 else if (_drawMode & (mDrawModes.faceBasedDrawModes | mDrawModes.hiddenLineBackgroundFaces))
395 mPrimitiveMode = PM_FACES;
396 else if (_drawMode & (mDrawModes.halffaceBasedDrawModes))
397 mPrimitiveMode = PM_HALFFACES;
398 else if (_drawMode & (mDrawModes.edgesOnCells))
399 mPrimitiveMode = PM_EDGES_ON_CELLS;
400 else if (_drawMode & ((mDrawModes.edgeBasedDrawModes) & ~(mDrawModes.irregularInnerEdges | mDrawModes.irregularOuterEdges)))
401 mPrimitiveMode = PM_EDGES;
402 else if (_drawMode & (mDrawModes.irregularInnerEdges | mDrawModes.irregularOuterEdges)) // note: this has to be checked after _drawMode & (mDrawModes.edgeBasedDrawModes)
403 mPrimitiveMode = PM_IRREGULAR_EDGES; // if this is true, irregular edges are already included
404 else if (_drawMode & (mDrawModes.halfedgeBasedDrawModes))
405 mPrimitiveMode = PM_HALFEDGES;
406 else if (_drawMode & (mDrawModes.verticesOnCells))
407 mPrimitiveMode = PM_VERTICES_ON_CELLS;
408 else if (_drawMode & (mDrawModes.vertexBasedDrawModes))
409 mPrimitiveMode = PM_VERTICES;
410 else
411 mPrimitiveMode = PM_NONE;
412
413
414 }
415
416
423 template <class VolumeMesh>
424 void VolumeMeshBufferManager<VolumeMesh>::clearCutPlanes()
425 {
426 cut_planes_.clear();
427 invalidateGeometry();
428 mCellInsidenessValid = false;
429 }
430
438 template <class VolumeMesh>
439 void VolumeMeshBufferManager<VolumeMesh>::addCutPlane(const typename VolumeMeshBufferManager<VolumeMesh>::Plane& _p)
440 {
441 cut_planes_.push_back(_p);
442 invalidateGeometry();
443 mCellInsidenessValid = false;
444 }
445
456 template <class VolumeMesh>
457 void VolumeMeshBufferManager<VolumeMesh>::addCutPlane(const ACG::Vec3d &_p, const ACG::Vec3d &_n, const ACG::Vec3d &_xsize, const ACG::Vec3d &_ysize)
458 {
459 addCutPlane(Plane(_p, _n, _xsize, _ysize));
460 }
461
469 template <class VolumeMesh>
470 bool VolumeMeshBufferManager<VolumeMesh>::is_inside(const ACG::Vec3d& _p)
471 {
472 for(typename std::vector<Plane>::iterator it = cut_planes_.begin(); it != cut_planes_.end(); ++it) {
473 // get local position
474 ACG::Vec3d pl = _p - it->position;
475 // evaluate dot products
476 double pn = (pl | it->normal);
477 double px = (pl | it->xdirection);
478 double py = (pl | it->ydirection);
479
480 if (pn < 0.0 && px > -0.5 && px < 0.5 && py > -0.5 && py < 0.5)
481 return false;
482 }
483
484 return true;
485 }
486
496 template <class VolumeMesh>
497 bool VolumeMeshBufferManager<VolumeMesh>::is_inside(const VertexHandle& _vh)
498 {
499 if ( cut_planes_.empty() ) return true;
500 return is_inside(mMesh.vertex(_vh));
501 }
502
512 template <class VolumeMesh>
513 bool VolumeMeshBufferManager<VolumeMesh>::is_inside(const HalfEdgeHandle& _heh)
514 {
515 if ( cut_planes_.empty() ) return true;
516 Edge e(mMesh.halfedge(_heh));
517 return is_inside(mMesh.vertex(e.from_vertex())) && is_inside(mMesh.vertex(e.to_vertex()));
518 }
519
529 template <class VolumeMesh>
530 bool VolumeMeshBufferManager<VolumeMesh>::is_inside(const EdgeHandle& _eh)
531 {
532 if ( cut_planes_.empty() ) return true;
533 Edge e(mMesh.edge(_eh));
534 return is_inside(mMesh.vertex(e.from_vertex())) && is_inside(mMesh.vertex(e.to_vertex()));
535 }
536
546 template <class VolumeMesh>
547 bool VolumeMeshBufferManager<VolumeMesh>::is_inside(const HalfFaceHandle& _hfh)
548 {
549 if ( cut_planes_.empty() ) return true;
550 for (OpenVolumeMesh::HalfFaceVertexIter hfv_it = mMesh.hfv_iter(_hfh); hfv_it; ++hfv_it)
551 if (!is_inside(*hfv_it)) return false;
552
553 return true;
554 }
555
565 template <class VolumeMesh>
566 bool VolumeMeshBufferManager<VolumeMesh>::is_inside(const FaceHandle& _fh)
567 {
568 if ( cut_planes_.empty() ) return true;
569 return is_inside(mMesh.halfface_handle(_fh,0));
570 }
571
583 template <class VolumeMesh>
584 bool VolumeMeshBufferManager<VolumeMesh>::is_inside(const CellHandle& _ch)
585 {
586 if (!mCellInsidenessValid)
587 calculateCellInsideness();
588
589 return mCellInsideness[_ch.idx()];
590 }
591
592
599 template <class VolumeMesh>
600 void VolumeMeshBufferManager<VolumeMesh>::calculateCellInsideness()
601 {
602 if (mCellInsideness.size() != mMesh.n_cells())
603 mCellInsideness.resize(mMesh.n_cells());
604
605 for (unsigned int i = 0; i < mMesh.n_cells(); i++)
606 {
607 CellHandle ch = CellHandle(i);
608 bool inside;
609 ACG::Vec3d cog = getCOG(ch);
610 if ( cut_planes_.empty() )
611 inside = true;
612 else
613 {
614 inside = true;
615 for (OpenVolumeMesh::CellVertexIter cv_it = mMesh.cv_iter(ch); cv_it; ++cv_it)
616 {
617 ACG::Vec3d vertexPos = mScale * mMesh.vertex(*cv_it) + (1-mScale) * cog;
618 if (!is_inside(vertexPos)) inside = false;
619 }
620 }
621 mCellInsideness[i] = inside;
622 }
623
624 mCellInsidenessValid = true;
625 }
626
627
635 template <class VolumeMesh>
636 bool VolumeMeshBufferManager<VolumeMesh>::optionsChanged()
637 {
638 return mCurrentPrimitiveMode != mPrimitiveMode ||
639 mCurrentNormalMode != mNormalMode ||
640 mCurrentColorMode != mColorMode ||
641 mCurrentSkipUnselected != mSkipUnselected ||
642 mCurrentShowIrregularInnerEdges != mShowIrregularInnerEdges ||
643 mCurrentShowIrregularOuterValence2Edges != mShowIrregularOuterValence2Edges ||
644 mCurrentSkipRegularEdges != mSkipRegularEdges ||
645 mCurrentBoundaryOnly != mBoundaryOnly;
646 }
647
653 template <class VolumeMesh>
654 void VolumeMeshBufferManager<VolumeMesh>::saveOptions()
655 {
656 mCurrentPrimitiveMode = mPrimitiveMode;
657 mCurrentNormalMode = mNormalMode;
658 mCurrentColorMode = mColorMode;
659 mCurrentSkipUnselected = mSkipUnselected;
660 mCurrentShowIrregularInnerEdges = mShowIrregularInnerEdges;
661 mCurrentShowIrregularOuterValence2Edges = mShowIrregularOuterValence2Edges;
662 mCurrentSkipRegularEdges = mSkipRegularEdges;
663 mCurrentBoundaryOnly = mBoundaryOnly;
664 mCurrentVertexSize = mVertexSize;
665 mCurrentNormalOffset = mNormalOffset;
666 mCurrentColorOffset = mColorOffset;
667 mCurrentNumOfVertices = mNumOfVertices;
668 }
669
670
679 template <class VolumeMesh>
680 ACG::Vec4f VolumeMeshBufferManager<VolumeMesh>::getValenceColorCode(unsigned int _valence, bool _inner) const {
681
682 if(_inner && _valence == 3) {
683 return ACG::Vec4f(0.0f, 1.0f, 1.0f, 1.0f);
684 } else if(_inner && _valence == 5) {
685 return ACG::Vec4f(1.0f, 0.0f, 1.0f, 1.0f);
686 } else if(!_inner && _valence > 3) {
687 return ACG::Vec4f(0.0f, 1.0f, 0.0f, 1.0f);
688 } else if(!_inner && _valence == 2) {
689 return ACG::Vec4f(1.0f, 1.0f, 0.0f, 1.0f);
690 } else if(_inner && _valence > 5) {
691 return ACG::Vec4f(0.5f, 1.0f, 0.5f, 1.0f);
692 }
693 return ACG::Vec4f(0.0f, 0.0f, 0.0f, 1.0f);
694 }
695
701 template <class VolumeMesh>
702 void VolumeMeshBufferManager<VolumeMesh>::countNumOfVertices()
703 {
704 unsigned int numOfVertices = 0;
705
706 if (mSkipUnselected) //only count selected
707 {
708 if (mPrimitiveMode == PM_CELLS)
709 {
710 OpenVolumeMesh::CellIter c_begin(mMesh.cells_begin()), c_end(mMesh.cells_end());
711 for (OpenVolumeMesh::CellIter c_it = c_begin; c_it != c_end; ++c_it)
712 if (mStatusAttrib[*c_it].selected() && is_inside(*c_it))
713 {
714 std::vector<HalfFaceHandle> hfs = mMesh.cell(*c_it).halffaces();
715 for (unsigned int i = 0; i < hfs.size(); ++i)
716 numOfVertices += ((mMesh.valence(mMesh.face_handle(hfs[i])))-2)*3;
717 }
718 }
719 else if (mPrimitiveMode == PM_FACES)
720 {
721 OpenVolumeMesh::FaceIter f_begin(mMesh.faces_begin()), f_end(mMesh.faces_end());
722 for (OpenVolumeMesh::FaceIter f_it = f_begin; f_it != f_end; ++f_it)
723 if (mStatusAttrib[*f_it].selected() && is_inside(*f_it) && (!mBoundaryOnly || mMesh.is_boundary(*f_it)))
724 numOfVertices += ((mMesh.valence(*f_it))-2)*3; //additional vertices are added for faces with more than 3 adjacent vertices
725 }
726 else if (mPrimitiveMode == PM_FACES_ON_CELLS)
727 {
728 OpenVolumeMesh::FaceIter f_begin(mMesh.faces_begin()), f_end(mMesh.faces_end());
729 for (OpenVolumeMesh::FaceIter f_it = f_begin; f_it != f_end; ++f_it)
730 if (mStatusAttrib[*f_it].selected())
731 numOfVertices += ((mMesh.valence(*f_it))-2)*3*getNumOfIncidentCells(*f_it); //additional vertices are added for faces with more than 3 adjacent vertices
732 }
733 else if (mPrimitiveMode == PM_HALFFACES)
734 {
735 OpenVolumeMesh::HalfFaceIter hf_begin(mMesh.halffaces_begin()), hf_end(mMesh.halffaces_end());
736 for (OpenVolumeMesh::HalfFaceIter hf_it = hf_begin; hf_it != hf_end; ++hf_it)
737 if (mStatusAttrib[*hf_it].selected() && is_inside(*hf_it) && (!mBoundaryOnly || mMesh.is_boundary(*hf_it)))
738 numOfVertices += ((mMesh.valence(mMesh.face_handle(*hf_it)))-2)*3; //additional vertices are added for faces with more than 3 adjacent vertices
739 }
740 else if (mPrimitiveMode == PM_EDGES)
741 {
742 OpenVolumeMesh::EdgeIter e_begin(mMesh.edges_begin()), e_end(mMesh.edges_end());
743 for (OpenVolumeMesh::EdgeIter e_it = e_begin; e_it != e_end; ++e_it)
744 if (mStatusAttrib[*e_it].selected() && is_inside(*e_it) && (!mBoundaryOnly || mMesh.is_boundary(*e_it)))
745 numOfVertices += 2;
746 }
747 else if (mPrimitiveMode == PM_EDGES_ON_CELLS)
748 {
749 OpenVolumeMesh::EdgeIter e_begin(mMesh.edges_begin()), e_end(mMesh.edges_end());
750 for (OpenVolumeMesh::EdgeIter e_it = e_begin; e_it != e_end; ++e_it)
751 if (mStatusAttrib[*e_it].selected())
752 numOfVertices += 2*getNumOfIncidentCells(*e_it);
753 }
754 else if (mPrimitiveMode == PM_HALFEDGES)
755 {
756 OpenVolumeMesh::HalfEdgeIter he_begin(mMesh.halfedges_begin()), he_end(mMesh.halfedges_end());
757 for (OpenVolumeMesh::HalfEdgeIter he_it = he_begin; he_it != he_end; ++he_it)
758 if (mStatusAttrib[*he_it].selected() && is_inside(*he_it) && (!mBoundaryOnly || mMesh.is_boundary(*he_it)))
759 numOfVertices += 2;
760 }
761 else if (mPrimitiveMode == PM_VERTICES)
762 {
763 OpenVolumeMesh::VertexIter v_begin(mMesh.vertices_begin()), v_end(mMesh.vertices_end());
764 for (OpenVolumeMesh::VertexIter v_it = v_begin; v_it != v_end; ++v_it)
765 if (mStatusAttrib[*v_it].selected() && is_inside(*v_it) && (!mBoundaryOnly || mMesh.is_boundary(*v_it)))
766 numOfVertices += 1;
767 }
768 else if (mPrimitiveMode == PM_VERTICES_ON_CELLS)
769 {
770 OpenVolumeMesh::VertexIter v_begin(mMesh.vertices_begin()), v_end(mMesh.vertices_end());
771 for (OpenVolumeMesh::VertexIter v_it = v_begin; v_it != v_end; ++v_it)
772 if (mStatusAttrib[*v_it].selected())
773 numOfVertices += getNumOfIncidentCells(*v_it);
774 }
775 }
776 else
777 {
778 if (mPrimitiveMode == PM_VERTICES_ON_CELLS)
779 {
780 for (unsigned int i = 0; i < mMesh.n_vertices(); i++)
781 numOfVertices += getNumOfIncidentCells(VertexHandle(i));
782 }
783 else if (mPrimitiveMode == PM_VERTICES)
784 {
785 for (unsigned int i = 0; i < mMesh.n_vertices(); i++)
786 if (is_inside(VertexHandle(i)) && (!mBoundaryOnly || mMesh.is_boundary(VertexHandle(i))))
787 numOfVertices += 1;
788 }
789 else if (mPrimitiveMode == PM_FACES)
790 {
791 OpenVolumeMesh::FaceIter f_begin(mMesh.faces_begin()), f_end(mMesh.faces_end());
792 for (OpenVolumeMesh::FaceIter f_it = f_begin; f_it != f_end; ++f_it)
793 if (is_inside(*f_it) && (!mBoundaryOnly || mMesh.is_boundary(*f_it)))
794 numOfVertices += ((mMesh.valence(*f_it))-2)*3; //additional vertices are added for faces with more than 3 adjacent vertices
795 }
796 else if (mPrimitiveMode == PM_FACES_ON_CELLS)
797 {
798 OpenVolumeMesh::FaceIter f_begin(mMesh.faces_begin()), f_end(mMesh.faces_end());
799 for (OpenVolumeMesh::FaceIter f_it = f_begin; f_it != f_end; ++f_it)
800 numOfVertices += ((mMesh.valence(*f_it))-2)*3*getNumOfIncidentCells(*f_it); //additional vertices are added for faces with more than 3 adjacent vertices
801 }
802 else if (mPrimitiveMode == PM_HALFFACES)
803 {
804 OpenVolumeMesh::HalfFaceIter hf_begin(mMesh.halffaces_begin()), hf_end(mMesh.halffaces_end());
805 for (OpenVolumeMesh::HalfFaceIter hf_it = hf_begin; hf_it != hf_end; ++hf_it)
806 if (is_inside(*hf_it) && (!mBoundaryOnly || mMesh.is_boundary(*hf_it)))
807 numOfVertices += ((mMesh.valence(mMesh.face_handle(*hf_it)))-2)*3; //additional vertices are added for faces with more than 3 adjacent vertices
808 }
809 else if (mPrimitiveMode == PM_CELLS)
810 {
811 OpenVolumeMesh::CellIter c_begin(mMesh.cells_begin()), c_end(mMesh.cells_end());
812 for (OpenVolumeMesh::CellIter c_it = c_begin; c_it != c_end; ++c_it)
813 {
814 if (is_inside(*c_it))
815 {
816 std::vector<HalfFaceHandle> hfs = mMesh.cell(*c_it).halffaces();
817 for (unsigned int i = 0; i < hfs.size(); ++i)
818 numOfVertices += ((mMesh.valence(mMesh.face_handle(hfs[i])))-2)*3;
819 }
820 }
821 }
822 else if (mPrimitiveMode == PM_EDGES_ON_CELLS)
823 {
824 for (OpenVolumeMesh::EdgeIter e_it = mMesh.edges_begin(); e_it != mMesh.edges_end(); ++e_it)
825 numOfVertices += 2*getNumOfIncidentCells(*e_it);
826 }
827 else if ( mPrimitiveMode == PM_EDGES ) //all edges are drawn, so irregular ones are already included
828 {
829 for (OpenVolumeMesh::EdgeIter e_it = mMesh.edges_begin(); e_it != mMesh.edges_end(); ++e_it)
830 if (is_inside(*e_it) && (!mBoundaryOnly || mMesh.is_boundary(*e_it)))
831 numOfVertices += 2;
832 }
833 else if ( mPrimitiveMode == PM_IRREGULAR_EDGES )
834 {
835 for (OpenVolumeMesh::EdgeIter e_it = mMesh.edges_begin(); e_it != mMesh.edges_end(); ++e_it)
836 if (is_inside(*e_it) && (!mBoundaryOnly || mMesh.is_boundary(*e_it)))
837 {
838 bool boundary = mMesh.is_boundary(*e_it);
839 unsigned int valence = mMesh.valence(*e_it);
840
841 // Skip regular edges
842 if(( boundary && valence == 3) || (!boundary && valence == 4)) continue;
843 //skip boundary valence 2 edges if not drawn
844 if ((!(mShowIrregularOuterValence2Edges)) && ( boundary && valence == 2)) continue;
845 //skip irregular inner edges if not drawn
846 if ((!(mShowIrregularInnerEdges)) && (( !boundary && valence != 4) ||
847 ( boundary && valence < 2) ||
848 ( boundary && valence > 3))) continue;
849
850 numOfVertices += 2;
851 }
852 }
853 else if ( mPrimitiveMode == PM_HALFEDGES )
854 {
855 for (OpenVolumeMesh::HalfEdgeIter he_it = mMesh.halfedges_begin(); he_it != mMesh.halfedges_end(); ++he_it)
856 if (is_inside(*he_it) && (!mBoundaryOnly || mMesh.is_boundary(*he_it)))
857 numOfVertices += 2;
858 }
859 else /*if ( mPrimitiveMode == PM_NONE)*/
860 {
861 numOfVertices = 0;
862 }
863 }
864
865 mNumOfVertices = numOfVertices;
866 }
867
875 template <class VolumeMesh>
876 int VolumeMeshBufferManager<VolumeMesh>::getNumOfIncidentCells(OpenVolumeMesh::FaceHandle _fh)
877 {
878 int incidentCells = 0;
879 OpenVolumeMesh::HalfFaceHandle hf0 = mMesh.halfface_handle(_fh, 0);
880 if (mMesh.incident_cell(hf0) != CellHandle(-1))
881 if (is_inside(mMesh.incident_cell(hf0)))
882 incidentCells += 1;
883 OpenVolumeMesh::HalfFaceHandle hf1 = mMesh.halfface_handle(_fh, 1);
884 if (mMesh.incident_cell(hf1) != CellHandle(-1))
885 if (is_inside(mMesh.incident_cell(hf1)))
886 incidentCells += 1;
887 return incidentCells;
888 }
889
897 template <class VolumeMesh>
898 int VolumeMeshBufferManager<VolumeMesh>::getNumOfIncidentCells(OpenVolumeMesh::EdgeHandle _eh)
899 {
900 int incidentCells = 0;
901 OpenVolumeMesh::HalfEdgeHandle heh = mMesh.halfedge_handle(_eh, 0);
902 for (OpenVolumeMesh::HalfEdgeCellIter hec_it = OpenVolumeMesh::HalfEdgeCellIter(heh,&mMesh); hec_it.valid(); ++hec_it)
903 if (hec_it->idx() != -1)
904 if (is_inside(*hec_it))
905 incidentCells++;
906 return incidentCells;
907 }
908
916 template <class VolumeMesh>
917 int VolumeMeshBufferManager<VolumeMesh>::getNumOfIncidentCells(OpenVolumeMesh::VertexHandle _vh)
918 {
919 int incidentCells = 0;
920 for (OpenVolumeMesh::VertexCellIter vc_it = OpenVolumeMesh::VertexCellIter(_vh,&mMesh); vc_it; ++vc_it)
921 if (vc_it->idx() != -1)
922 if (is_inside(*vc_it))
923 incidentCells++;
924 return incidentCells;
925 }
926
934 template <class VolumeMesh>
935 ACG::Vec3d VolumeMeshBufferManager<VolumeMesh>::getCOG(OpenVolumeMesh::CellHandle _ch)
936 {
937 if (!mCogsValid)
938 calculateCOGs();
939
940 return mCogs[_ch.idx()];
941 }
942
950 template <class VolumeMesh>
951 void VolumeMeshBufferManager<VolumeMesh>::calculateCOGs()
952 {
953 if (mCogs.size() != mMesh.n_cells())
954 mCogs.resize(mMesh.n_cells());
955
956 OpenVolumeMesh::CellIter c_begin(mMesh.cells_begin()), c_end(mMesh.cells_end());
957 for (OpenVolumeMesh::CellIter c_it = c_begin; c_it != c_end; ++c_it)
958 {
959
960 std::vector<HalfFaceHandle> hfs = mMesh.cell(*c_it).halffaces();
961 ACG::Vec3d cog = ACG::Vec3d(0.0f);
962 int count = 0;
963 for (unsigned int i = 0; i < hfs.size(); ++i)
964 for (OpenVolumeMesh::HalfFaceVertexIter hfv_it = mMesh.hfv_iter(hfs[i]); hfv_it; ++hfv_it)
965 {
966 cog += mMesh.vertex(*hfv_it);
967 count += 1;
968 }
969 cog = 1.0/count * cog;
970
971 mCogs[c_it->idx()] = cog;
972 }
973
974 mCogsValid = true;
975 }
976
982 template <class VolumeMesh>
983 bool VolumeMeshBufferManager<VolumeMesh>::positionsNeedRebuild()
984 {
985 return (mGeometryChanged) ||
986 (mVertexSize != mCurrentVertexSize) ||
987 (mPrimitiveMode != mCurrentPrimitiveMode) ||
988 (mNumOfVertices != mCurrentNumOfVertices);
989 }
990
996 template <class VolumeMesh>
997 bool VolumeMeshBufferManager<VolumeMesh>::colorsNeedRebuild()
998 {
999 return (mColorsChanged) ||
1000 (mVertexSize != mCurrentVertexSize) ||
1001 (mNumOfVertices != mCurrentNumOfVertices) ||
1002 (mPrimitiveMode != mCurrentPrimitiveMode) ||
1003 (mColorOffset != mCurrentColorOffset) ||
1004 (mColorMode != mCurrentColorMode) ||
1005 (mShowIrregularInnerEdges != mCurrentShowIrregularInnerEdges) ||
1006 (mShowIrregularOuterValence2Edges != mCurrentShowIrregularOuterValence2Edges);
1007 }
1008
1014 template <class VolumeMesh>
1015 bool VolumeMeshBufferManager<VolumeMesh>::texCoordsNeedRebuild()
1016 {
1017 return (mTexCoordsChanged) ||
1018 (mVertexSize != mCurrentVertexSize) ||
1019 (mNumOfVertices != mCurrentNumOfVertices) ||
1020 (mPrimitiveMode != mCurrentPrimitiveMode) ||
1021 (mTexCoordOffset!= mCurrentTexCoordOffset);
1022 }
1023
1029 template <class VolumeMesh>
1030 bool VolumeMeshBufferManager<VolumeMesh>::normalsNeedRebuild()
1031 {
1032 return (mNormalsChanged) ||
1033 (mVertexSize != mCurrentVertexSize) ||
1034 (mPrimitiveMode != mCurrentPrimitiveMode) ||
1035 (mNormalOffset != mCurrentNormalOffset) ||
1036 (mNormalMode != mCurrentNormalMode) ||
1037 (mNumOfVertices != mCurrentNumOfVertices);
1038 }
1039
1045 template <class VolumeMesh>
1046 void VolumeMeshBufferManager<VolumeMesh>::buildVertexBuffer(unsigned char* _buffer)
1047 {
1048 unsigned int pos = 0;
1049
1050 if (mPrimitiveMode == PM_VERTICES)
1051 {
1052 for (unsigned int i = 0; i < mMesh.n_vertices(); ++i) {
1053 if (mSkipUnselected && !mStatusAttrib[VertexHandle(i)].selected()) continue;
1054 if (!is_inside(VertexHandle(i))) continue;
1055 if (mBoundaryOnly && !mMesh.is_boundary(VertexHandle(i))) continue;
1056 ACG::Vec3d p = mMesh.vertex(VertexHandle(i));
1057 addPositionToBuffer(p, _buffer, pos++);
1058 }
1059 }
1060 else if (mPrimitiveMode == PM_VERTICES_ON_CELLS)
1061 {
1062 for (unsigned int i = 0; i < mMesh.n_vertices(); ++i) {
1063 if (mSkipUnselected && !mStatusAttrib[VertexHandle(i)].selected()) continue;
1064 ACG::Vec3d p = mMesh.vertex(VertexHandle(i));
1065 for (OpenVolumeMesh::VertexCellIter vc_it = OpenVolumeMesh::VertexCellIter(VertexHandle(i),&mMesh); vc_it; ++vc_it)
1066 {
1067 ACG::Vec3d cog = getCOG(*vc_it);
1068 //ACG::Vec3d newPos = p*mScale + cog*(1-mScale);
1069 if (is_inside(*vc_it))
1070 addPositionToBuffer(p*mScale + cog*(1-mScale), _buffer, pos++);
1071 }
1072 }
1073 }
1074 else if (mPrimitiveMode == PM_FACES)
1075 {
1076 std::vector<ACG::Vec3d> vertices;
1077 OpenVolumeMesh::FaceIter f_begin(mMesh.faces_begin()), f_end(mMesh.faces_end());
1078 for (OpenVolumeMesh::FaceIter f_it = f_begin; f_it != f_end; ++f_it)
1079 {
1080 if (mSkipUnselected && !mStatusAttrib[*f_it].selected()) continue;
1081 if (mBoundaryOnly && !mMesh.is_boundary(*f_it)) continue;
1082 if (!is_inside(*f_it)) continue;
1083 vertices.clear();
1084 for (OpenVolumeMesh::HalfFaceVertexIter hfv_it = mMesh.hfv_iter(mMesh.halfface_handle(*f_it,0)); hfv_it; ++hfv_it)
1085 vertices.push_back(mMesh.vertex(*hfv_it));
1086
1087 for (unsigned int i = 0; i < vertices.size()-2; i++)
1088 {
1089 addPositionToBuffer(vertices[0], _buffer, pos++);
1090 addPositionToBuffer(vertices[i+1], _buffer, pos++);
1091 addPositionToBuffer(vertices[i+2], _buffer, pos++);
1092 }
1093 }
1094 }
1095 else if (mPrimitiveMode == PM_FACES_ON_CELLS)
1096 {
1097 std::vector<ACG::Vec3d> vertices;
1098 OpenVolumeMesh::FaceIter f_begin(mMesh.faces_begin()), f_end(mMesh.faces_end());
1099 for (OpenVolumeMesh::FaceIter f_it = f_begin; f_it != f_end; ++f_it)
1100 {
1101 if (mSkipUnselected && !mStatusAttrib[*f_it].selected()) continue;
1102 vertices.clear();
1103 for (OpenVolumeMesh::HalfFaceVertexIter hfv_it = mMesh.hfv_iter(mMesh.halfface_handle(*f_it,0)); hfv_it; ++hfv_it)
1104 vertices.push_back(mMesh.vertex(*hfv_it));
1105
1106 for (int i = 0; i < 2; i++)
1107 {
1108 OpenVolumeMesh::CellHandle ch = mMesh.incident_cell(mMesh.halfface_handle(*f_it,i));
1109 if (ch != CellHandle(-1))
1110 {
1111 if (!is_inside(ch)) continue;
1112 ACG::Vec3d cog = getCOG(ch);
1113 for (unsigned int i = 0; i < vertices.size()-2; i++)
1114 {
1115 //we dont care about the correct facing because we dont cull the back side of faces
1116 addPositionToBuffer(vertices[0]*mScale + cog*(1-mScale), _buffer, pos++);
1117 addPositionToBuffer(vertices[i+1]*mScale + cog*(1-mScale), _buffer, pos++);
1118 addPositionToBuffer(vertices[i+2]*mScale + cog*(1-mScale), _buffer, pos++);
1119 }
1120 }
1121 }
1122
1123 }
1124 }
1125 else if (mPrimitiveMode == PM_HALFFACES)
1126 {
1127 std::vector<ACG::Vec3d> vertices;
1128 OpenVolumeMesh::HalfFaceIter hf_begin(mMesh.halffaces_begin()), hf_end(mMesh.halffaces_end());
1129 for (OpenVolumeMesh::HalfFaceIter hf_it = hf_begin; hf_it != hf_end; ++hf_it)
1130 {
1131 if (mSkipUnselected && !mStatusAttrib[*hf_it].selected()) continue;
1132 if (mBoundaryOnly && !mMesh.is_boundary(*hf_it)) continue;
1133 if (!is_inside(*hf_it)) continue;
1134 vertices.clear();
1135 for (OpenVolumeMesh::HalfFaceVertexIter hfv_it = mMesh.hfv_iter(*hf_it); hfv_it; ++hfv_it)
1136 vertices.push_back(mMesh.vertex(*hfv_it));
1137
1138 for (unsigned int i = 0; i < vertices.size()-2; i++)
1139 {
1140 addPositionToBuffer(vertices[0], _buffer, pos++);
1141 addPositionToBuffer(vertices[i+1], _buffer, pos++);
1142 addPositionToBuffer(vertices[i+2], _buffer, pos++);
1143 }
1144 }
1145 }
1146 else if (mPrimitiveMode == PM_CELLS)
1147 {
1148 std::vector<ACG::Vec3d> vertices;
1149 OpenVolumeMesh::CellIter c_begin(mMesh.cells_begin()), c_end(mMesh.cells_end());
1150 for (OpenVolumeMesh::CellIter c_it = c_begin; c_it != c_end; ++c_it)
1151 {
1152 if (mSkipUnselected && !mStatusAttrib[*c_it].selected()) continue;
1153 if (!is_inside(*c_it)) continue;
1154 std::vector<HalfFaceHandle> hfs = mMesh.cell(*c_it).halffaces();
1155 ACG::Vec3d cog = getCOG(*c_it);
1156 for (unsigned int i = 0; i < hfs.size(); ++i)
1157 {
1158 vertices.clear();
1159 for (OpenVolumeMesh::HalfFaceVertexIter hfv_it = mMesh.hfv_iter(hfs[i]); hfv_it; ++hfv_it)
1160 vertices.push_back(mScale*mMesh.vertex(*hfv_it)+(1-mScale)*cog);
1161
1162 for (unsigned int i = 0; i < vertices.size()-2; i++)
1163 {
1164 addPositionToBuffer(vertices[0], _buffer, pos++);
1165 addPositionToBuffer(vertices[i+1], _buffer, pos++);
1166 addPositionToBuffer(vertices[i+2], _buffer, pos++);
1167 }
1168 }
1169 }
1170
1171 }
1172 else if (mPrimitiveMode == PM_EDGES)
1173 {
1174 OpenVolumeMesh::EdgeIter e_begin(mMesh.edges_begin()), e_end(mMesh.edges_end());
1175 for (OpenVolumeMesh::EdgeIter e_it = e_begin; e_it != e_end; ++e_it)
1176 {
1177 if (mSkipUnselected && !mStatusAttrib[*e_it].selected()) continue;
1178 if (mBoundaryOnly && !mMesh.is_boundary(*e_it)) continue;
1179 if (!is_inside(*e_it)) continue;
1180
1181 Edge e(mMesh.edge(*e_it));
1182 addPositionToBuffer(mMesh.vertex(e.from_vertex()), _buffer, pos++);
1183 addPositionToBuffer(mMesh.vertex(e.to_vertex()), _buffer, pos++);
1184 }
1185 }
1186 else if (mPrimitiveMode == PM_EDGES_ON_CELLS)
1187 {
1188 OpenVolumeMesh::EdgeIter e_begin(mMesh.edges_begin()), e_end(mMesh.edges_end());
1189 for (OpenVolumeMesh::EdgeIter e_it = e_begin; e_it != e_end; ++e_it)
1190 {
1191 if (mSkipUnselected && !mStatusAttrib[*e_it].selected()) continue;
1192
1193 Edge e(mMesh.edge(*e_it));
1194 OpenVolumeMesh::HalfEdgeHandle heh = mMesh.halfedge_handle(*e_it, 0);
1195 for (OpenVolumeMesh::HalfEdgeCellIter hec_it = OpenVolumeMesh::HalfEdgeCellIter(heh,&mMesh); hec_it.valid(); ++hec_it)
1196 {
1197 if (hec_it->idx() != -1)
1198 {
1199 if (!is_inside(*hec_it)) continue;
1200 ACG::Vec3d cog = getCOG(*hec_it);
1201 addPositionToBuffer(mMesh.vertex(e.from_vertex())*mScale + cog*(1-mScale), _buffer, pos++);
1202 addPositionToBuffer(mMesh.vertex(e.to_vertex()) *mScale + cog*(1-mScale), _buffer, pos++);
1203 }
1204 }
1205 }
1206 }
1207 else if (mPrimitiveMode == PM_IRREGULAR_EDGES)
1208 {
1209 OpenVolumeMesh::EdgeIter e_begin(mMesh.edges_begin()), e_end(mMesh.edges_end());
1210 for (OpenVolumeMesh::EdgeIter e_it = e_begin; e_it != e_end; ++e_it)
1211 {
1212 if (mSkipUnselected && !mStatusAttrib[*e_it].selected()) continue;
1213 if (mBoundaryOnly && !mMesh.is_boundary(*e_it)) continue;
1214 if (!is_inside(*e_it)) continue;
1215
1216 bool boundary = mMesh.is_boundary(*e_it);
1217 unsigned int valence = mMesh.valence(*e_it);
1218 // Skip regular
1219 if(( boundary && valence == 3) ||
1220 (!boundary && valence == 4)) continue;
1221 //skip boundary valence 2 edges if not drawn
1222 if ((!mShowIrregularOuterValence2Edges) && ( boundary && valence == 2)) continue;
1223 //skip irregular inner edges if not drawn
1224 if ((!mShowIrregularInnerEdges) && (( !boundary && valence != 4) ||
1225 ( boundary && valence < 2) ||
1226 ( boundary && valence > 3))) continue;
1227
1228 Edge e(mMesh.edge(*e_it));
1229 addPositionToBuffer(mMesh.vertex(e.from_vertex()), _buffer, pos++);
1230 addPositionToBuffer(mMesh.vertex(e.to_vertex()), _buffer, pos++);
1231 }
1232 }
1233 else if (mPrimitiveMode == PM_HALFEDGES)
1234 {
1235 OpenVolumeMesh::HalfEdgeIter he_begin(mMesh.halfedges_begin()), he_end(mMesh.halfedges_end());
1236 for (OpenVolumeMesh::HalfEdgeIter he_it = he_begin; he_it != he_end; ++he_it)
1237 {
1238 if (mSkipUnselected && !mStatusAttrib[*he_it].selected()) continue;
1239 if (mBoundaryOnly && !mMesh.is_boundary(*he_it)) continue;
1240 if (!is_inside(*he_it)) continue;
1241
1242 double lambda = 0.4;
1243 Edge e(mMesh.halfedge(*he_it));
1244 addPositionToBuffer(mMesh.vertex(e.from_vertex()), _buffer, pos++);
1245 addPositionToBuffer((1-lambda)*mMesh.vertex(e.from_vertex()) + lambda*mMesh.vertex(e.to_vertex()), _buffer, pos++);
1246 }
1247 }
1248 else /*if (mPrimitiveMode == PM_NONE)*/
1249 {
1250 //This case should not happen. Do nothing.
1251 }
1252 }
1253
1259 template <class VolumeMesh>
1260 void VolumeMeshBufferManager<VolumeMesh>::buildNormalBuffer(unsigned char* _buffer)
1261 {
1262 if (mNormalMode == NM_NONE) return;
1263
1264 unsigned int pos = 0;
1265
1266 if ((mPrimitiveMode == PM_FACES) && (mNormalMode == NM_FACE))
1267 {
1268 OpenVolumeMesh::FaceIter f_begin(mMesh.faces_begin()), f_end(mMesh.faces_end());
1269 for (OpenVolumeMesh::FaceIter f_it = f_begin; f_it != f_end; ++f_it)
1270 {
1271 if (mBoundaryOnly && !mMesh.is_boundary(*f_it)) continue;
1272 if (!is_inside(*f_it)) continue;
1273 ACG::Vec3d normal = mNormalAttrib[*f_it];
1274 unsigned int numOfVerticesInFace = mMesh.valence(*f_it);
1275
1276 for (unsigned int i = 0; i < numOfVerticesInFace - 2; i++)
1277 {
1278 addNormalToBuffer(normal, _buffer, pos++);
1279 addNormalToBuffer(normal, _buffer, pos++);
1280 addNormalToBuffer(normal, _buffer, pos++);
1281 }
1282 }
1283 }
1284 else if ((mPrimitiveMode == PM_FACES) && (mNormalMode == NM_VERTEX))
1285 {
1286 std::vector<ACG::Vec3d> normals;
1287 OpenVolumeMesh::FaceIter f_begin(mMesh.faces_begin()), f_end(mMesh.faces_end());
1288 for (OpenVolumeMesh::FaceIter f_it = f_begin; f_it != f_end; ++f_it)
1289 {
1290 if (mBoundaryOnly && !mMesh.is_boundary(*f_it)) continue;
1291 if (!is_inside(*f_it)) continue;
1292 normals.clear();
1293 for (OpenVolumeMesh::HalfFaceVertexIter hfv_it = mMesh.hfv_iter(mMesh.halfface_handle(*f_it,0)); hfv_it; ++hfv_it)
1294 normals.push_back(mNormalAttrib[*hfv_it]);
1295
1296 for (unsigned int i = 0; i < normals.size()-2; i++)
1297 {
1298 addNormalToBuffer(normals[0], _buffer, pos++);
1299 addNormalToBuffer(normals[i+1], _buffer, pos++);
1300 addNormalToBuffer(normals[i+2], _buffer, pos++);
1301 }
1302 }
1303 }
1304 else if ((mPrimitiveMode == PM_HALFFACES) && (mNormalMode == NM_HALFFACE))
1305 {
1306 OpenVolumeMesh::HalfFaceIter hf_begin(mMesh.halffaces_begin()), hf_end(mMesh.halffaces_end());
1307 for (OpenVolumeMesh::HalfFaceIter hf_it = hf_begin; hf_it != hf_end; ++hf_it)
1308 {
1309 if (mBoundaryOnly && !mMesh.is_boundary(*hf_it)) continue;
1310 if (!is_inside(*hf_it)) continue;
1311 ACG::Vec3d normal = mNormalAttrib[*hf_it];
1312 unsigned int numOfVerticesInCell = 0;
1313 for (OpenVolumeMesh::HalfFaceVertexIter hfv_it = mMesh.hfv_iter(*hf_it); hfv_it; ++hfv_it)
1314 ++numOfVerticesInCell;
1315
1316 for (unsigned int i = 0; i < numOfVerticesInCell- 2; i++)
1317 {
1318 addNormalToBuffer(normal, _buffer, pos++);
1319 addNormalToBuffer(normal, _buffer, pos++);
1320 addNormalToBuffer(normal, _buffer, pos++);
1321 }
1322 }
1323 }
1324 else if ((mPrimitiveMode == PM_HALFFACES) && (mNormalMode == NM_VERTEX))
1325 {
1326 std::vector<ACG::Vec3d> normals;
1327 OpenVolumeMesh::HalfFaceIter hf_begin(mMesh.halffaces_begin()), hf_end(mMesh.halffaces_end());
1328 for (OpenVolumeMesh::HalfFaceIter hf_it = hf_begin; hf_it != hf_end; ++hf_it)
1329 {
1330 if (mBoundaryOnly && !mMesh.is_boundary(*hf_it)) continue;
1331 if (!is_inside(*hf_it)) continue;
1332 normals.clear();
1333 for (OpenVolumeMesh::HalfFaceVertexIter hfv_it = mMesh.hfv_iter(*hf_it); hfv_it; ++hfv_it)
1334 normals.push_back(mNormalAttrib[*hfv_it]);
1335
1336 for (unsigned int i = 0; i < normals.size()-2; i++)
1337 {
1338 addNormalToBuffer(normals[0], _buffer, pos++);
1339 addNormalToBuffer(normals[i+1], _buffer, pos++);
1340 addNormalToBuffer(normals[i+2], _buffer, pos++);
1341 }
1342 }
1343 }
1344 else if ((mPrimitiveMode == PM_CELLS) && (mNormalMode == NM_HALFFACE))
1345 {
1346 OpenVolumeMesh::CellIter c_begin(mMesh.cells_begin()), c_end(mMesh.cells_end());
1347 for (OpenVolumeMesh::CellIter c_it = c_begin; c_it != c_end; ++c_it)
1348 {
1349 if (!is_inside(*c_it)) continue;
1350 std::vector<HalfFaceHandle> hfs = mMesh.cell(*c_it).halffaces();
1351 for (unsigned int i = 0; i < hfs.size(); ++i)
1352 {
1353 ACG::Vec3d normal = -1.0*mNormalAttrib[hfs[i]];
1354 unsigned int numOfVerticesInFace = mMesh.valence(mMesh.face_handle(hfs[i]));
1355
1356 for (unsigned int i = 0; i < numOfVerticesInFace-2; i++)
1357 {
1358 addNormalToBuffer(normal, _buffer, pos++);
1359 addNormalToBuffer(normal, _buffer, pos++);
1360 addNormalToBuffer(normal, _buffer, pos++);
1361 }
1362 }
1363 }
1364 }
1365 else if ((mPrimitiveMode == PM_CELLS) && (mNormalMode == NM_VERTEX))
1366 {
1367 std::vector<ACG::Vec3d> normals;
1368 OpenVolumeMesh::CellIter c_begin(mMesh.cells_begin()), c_end(mMesh.cells_end());
1369 for (OpenVolumeMesh::CellIter c_it = c_begin; c_it != c_end; ++c_it)
1370 {
1371 if (!is_inside(*c_it)) continue;
1372 std::vector<HalfFaceHandle> hfs = mMesh.cell(*c_it).halffaces();
1373
1374 for (unsigned int i = 0; i < hfs.size(); ++i)
1375 {
1376 normals.clear();
1377 for (OpenVolumeMesh::HalfFaceVertexIter hfv_it = mMesh.hfv_iter(hfs[i]); hfv_it; ++hfv_it)
1378 normals.push_back(mNormalAttrib[*hfv_it]);
1379
1380 for (unsigned int i = 0; i < normals.size()-2; i++)
1381 {
1382 addNormalToBuffer(normals[0], _buffer, pos++);
1383 addNormalToBuffer(normals[i+1], _buffer, pos++);
1384 addNormalToBuffer(normals[i+2], _buffer, pos++);
1385 }
1386 }
1387 }
1388 }
1389
1390 }
1391
1397 template <class VolumeMesh>
1398 void VolumeMeshBufferManager<VolumeMesh>::buildColorBuffer(unsigned char* _buffer)
1399 {
1400 unsigned int pos = 0;
1401
1402 if ((mPrimitiveMode == PM_VERTICES) && (mColorMode == CM_VERTEX))
1403 {
1404 for (unsigned int i = 0; i < mMesh.n_vertices(); ++i)
1405 {
1406 if (mBoundaryOnly && !mMesh.is_boundary(VertexHandle(i))) continue;
1407 if (!is_inside(VertexHandle(i))) continue;
1408 ACG::Vec4f color = mColorAttrib[VertexHandle(i)];
1409 addColorToBuffer(color, _buffer, pos++);
1410 }
1411 }
1412 else if ((mPrimitiveMode == PM_FACES) && (mColorMode == CM_VERTEX))
1413 {
1414 std::vector<ACG::Vec4f> colors;
1415 OpenVolumeMesh::FaceIter f_begin(mMesh.faces_begin()), f_end(mMesh.faces_end());
1416 for (OpenVolumeMesh::FaceIter f_it = f_begin; f_it != f_end; ++f_it)
1417 {
1418 if (mBoundaryOnly && !mMesh.is_boundary(*f_it)) continue;
1419 if (!is_inside(*f_it)) continue;
1420 colors.clear();
1421
1422 for (OpenVolumeMesh::HalfFaceVertexIter hfv_it = mMesh.hfv_iter(mMesh.halfface_handle(*f_it,0)); hfv_it; ++hfv_it)
1423 colors.push_back(mColorAttrib[*hfv_it]);
1424
1425 for (unsigned int i = 0; i < (colors.size()-2); i++)
1426 {
1427 addColorToBuffer(colors[0], _buffer, pos++);
1428 addColorToBuffer(colors[i+1], _buffer, pos++);
1429 addColorToBuffer(colors[i+2], _buffer, pos++);
1430 }
1431 }
1432 }
1433 else if ((mPrimitiveMode == PM_FACES) && (mColorMode == CM_FACE))
1434 {
1435 OpenVolumeMesh::FaceIter f_begin(mMesh.faces_begin()), f_end(mMesh.faces_end());
1436 for (OpenVolumeMesh::FaceIter f_it = f_begin; f_it != f_end; ++f_it)
1437 {
1438 if (mBoundaryOnly && !mMesh.is_boundary(*f_it)) continue;
1439 if (!is_inside(*f_it)) continue;
1440 ACG::Vec4f color = mColorAttrib[*f_it];
1441
1442 unsigned int numOfVerticesInFace = mMesh.valence(*f_it);
1443 unsigned int numOfDrawnTriangles = numOfVerticesInFace-2;
1444
1445 for (unsigned int i = 0; i < numOfDrawnTriangles*3; i++)
1446 addColorToBuffer(color, _buffer, pos++);
1447 }
1448 }
1449 else if ((mPrimitiveMode == PM_HALFFACES) && (mColorMode == CM_HALFFACE))
1450 {
1451 OpenVolumeMesh::HalfFaceIter hf_begin(mMesh.halffaces_begin()), hf_end(mMesh.halffaces_end());
1452 for (OpenVolumeMesh::HalfFaceIter hf_it = hf_begin; hf_it != hf_end; ++hf_it)
1453 {
1454 if (mBoundaryOnly && !mMesh.is_boundary(*hf_it)) continue;
1455 if (!is_inside(*hf_it)) continue;
1456 ACG::Vec4f color = mColorAttrib[*hf_it];
1457
1458 unsigned int numOfVerticesInFace = mMesh.valence(mMesh.face_handle(*hf_it));
1459 unsigned int numOfDrawnTriangles = numOfVerticesInFace-2;
1460
1461 for (unsigned int i = 0; i < numOfDrawnTriangles*3; i++)
1462 addColorToBuffer(color, _buffer, pos++);
1463 }
1464 }
1465 else if ((mPrimitiveMode == PM_HALFFACES) && (mColorMode == CM_VERTEX))
1466 {
1467 std::vector<ACG::Vec4f> colors;
1468 OpenVolumeMesh::HalfFaceIter hf_begin(mMesh.halffaces_begin()), hf_end(mMesh.halffaces_end());
1469 for (OpenVolumeMesh::HalfFaceIter hf_it = hf_begin; hf_it != hf_end; ++hf_it)
1470 {
1471 if (mBoundaryOnly && !mMesh.is_boundary(*hf_it)) continue;
1472 if (!is_inside(*hf_it)) continue;
1473 colors.clear();
1474
1475 for (OpenVolumeMesh::HalfFaceVertexIter hfv_it = mMesh.hfv_iter(*hf_it); hfv_it; ++hfv_it)
1476 colors.push_back(mColorAttrib[*hfv_it]);
1477
1478 for (unsigned int i = 0; i < (colors.size()-2); i++)
1479 {
1480 addColorToBuffer(colors[0], _buffer, pos++);
1481 addColorToBuffer(colors[i+1], _buffer, pos++);
1482 addColorToBuffer(colors[i+2], _buffer, pos++);
1483 }
1484 }
1485 }
1486 else if ((mPrimitiveMode == PM_CELLS) && (mColorMode == CM_CELL))
1487 {
1488 OpenVolumeMesh::CellIter c_begin(mMesh.cells_begin()), c_end(mMesh.cells_end());
1489 for (OpenVolumeMesh::CellIter c_it = c_begin; c_it != c_end; ++c_it)
1490 {
1491 if (!is_inside(*c_it)) continue;
1492 ACG::Vec4f color = mColorAttrib[*c_it];
1493 std::vector<HalfFaceHandle> hfs = mMesh.cell(*c_it).halffaces();
1494 for (unsigned int i = 0; i < hfs.size(); ++i)
1495 {
1496 unsigned int numOfVerticesInHalfface = 0;
1497 for (OpenVolumeMesh::HalfFaceVertexIter hfv_it = mMesh.hfv_iter(hfs[i]); hfv_it; ++hfv_it)
1498 ++numOfVerticesInHalfface;
1499
1500 unsigned int numOfDrawnFaces = numOfVerticesInHalfface-2;
1501 for (unsigned int i = 0; i < numOfDrawnFaces*3; i++)
1502 addColorToBuffer(color, _buffer, pos++);
1503 }
1504 }
1505 }
1506 else if ((mPrimitiveMode == PM_CELLS) && (mColorMode == CM_HALFFACE))
1507 {
1508 OpenVolumeMesh::CellIter c_begin(mMesh.cells_begin()), c_end(mMesh.cells_end());
1509 for (OpenVolumeMesh::CellIter c_it = c_begin; c_it != c_end; ++c_it)
1510 {
1511 if (!is_inside(*c_it)) continue;
1512 std::vector<HalfFaceHandle> hfs = mMesh.cell(*c_it).halffaces();
1513 for (unsigned int i = 0; i < hfs.size(); ++i)
1514 {
1515 ACG::Vec4f color = mColorAttrib[hfs[i]];
1516 unsigned int numOfVerticesInHalfface = 0;
1517 for (OpenVolumeMesh::HalfFaceVertexIter hfv_it = mMesh.hfv_iter(hfs[i]); hfv_it; ++hfv_it)
1518 ++numOfVerticesInHalfface;
1519
1520 unsigned int numOfDrawnFaces = numOfVerticesInHalfface-2;
1521 for (unsigned int i = 0; i < numOfDrawnFaces*3; i++)
1522 addColorToBuffer(color, _buffer, pos++);
1523 }
1524 }
1525 }
1526 else if ((mPrimitiveMode == PM_CELLS) && (mColorMode == CM_FACE))
1527 {
1528 OpenVolumeMesh::CellIter c_begin(mMesh.cells_begin()), c_end(mMesh.cells_end());
1529 for (OpenVolumeMesh::CellIter c_it = c_begin; c_it != c_end; ++c_it)
1530 {
1531 if (!is_inside(*c_it)) continue;
1532 std::vector<HalfFaceHandle> hfs = mMesh.cell(*c_it).halffaces();
1533 for (unsigned int i = 0; i < hfs.size(); ++i)
1534 {
1535 ACG::Vec4f color = mColorAttrib[mMesh.face_handle(hfs[i])];
1536 unsigned int numOfVerticesInHalfface = 0;
1537 for (OpenVolumeMesh::HalfFaceVertexIter hfv_it = mMesh.hfv_iter(hfs[i]); hfv_it; ++hfv_it)
1538 ++numOfVerticesInHalfface;
1539
1540 unsigned int numOfDrawnFaces = numOfVerticesInHalfface-2;
1541 for (unsigned int i = 0; i < numOfDrawnFaces*3; i++)
1542 addColorToBuffer(color, _buffer, pos++);
1543 }
1544 }
1545 }
1546 else if ((mPrimitiveMode == PM_CELLS) && (mColorMode == CM_VERTEX))
1547 {
1548 std::vector<ACG::Vec4f> colors;
1549 OpenVolumeMesh::CellIter c_begin(mMesh.cells_begin()), c_end(mMesh.cells_end());
1550 for (OpenVolumeMesh::CellIter c_it = c_begin; c_it != c_end; ++c_it)
1551 {
1552 if (!is_inside(*c_it)) continue;
1553 std::vector<HalfFaceHandle> hfs = mMesh.cell(*c_it).halffaces();
1554 for (unsigned int i = 0; i < hfs.size(); ++i)
1555 {
1556 colors.clear();
1557 for (OpenVolumeMesh::HalfFaceVertexIter hfv_it = mMesh.hfv_iter(hfs[i]); hfv_it; ++hfv_it)
1558 colors.push_back(mColorAttrib[*hfv_it]);
1559
1560 for (unsigned int i = 0; i < colors.size()-2; i++)
1561 {
1562 addColorToBuffer(colors[0], _buffer, pos++);
1563 addColorToBuffer(colors[i+1], _buffer, pos++);
1564 addColorToBuffer(colors[i+2], _buffer, pos++);
1565 }
1566 }
1567 }
1568 }
1569 else if ((mPrimitiveMode == PM_EDGES) && (mColorMode == CM_EDGE))
1570 {
1571 OpenVolumeMesh::EdgeIter e_begin(mMesh.edges_begin()), e_end(mMesh.edges_end());
1572 for (OpenVolumeMesh::EdgeIter e_it = e_begin; e_it != e_end; ++e_it)
1573 {
1574 if (mBoundaryOnly && !mMesh.is_boundary(*e_it)) continue;
1575 if (!is_inside(*e_it)) continue;
1576 ACG::Vec4f color = mColorAttrib[*e_it];
1577 addColorToBuffer(color, _buffer, pos++);
1578 addColorToBuffer(color, _buffer, pos++);
1579 }
1580 }
1581 else if ((mPrimitiveMode == PM_EDGES) && (mShowIrregularInnerEdges || mShowIrregularOuterValence2Edges))
1582 {
1583 OpenVolumeMesh::EdgeIter e_begin(mMesh.edges_begin()), e_end(mMesh.edges_end());
1584 for (OpenVolumeMesh::EdgeIter e_it = e_begin; e_it != e_end; ++e_it)
1585 {
1586 if (mBoundaryOnly && !mMesh.is_boundary(*e_it)) continue;
1587 if (!is_inside(*e_it)) continue;
1588
1589 bool boundary = mMesh.is_boundary(*e_it);
1590 unsigned int valence = mMesh.valence(*e_it);
1591
1592 bool isIrregularInner = ( boundary && valence < 2) || ( boundary && valence > 3) || (!boundary && valence != 4);
1593 bool isIrregularOuterValence2 = ( boundary && valence == 2);
1594
1595 ACG::Vec4f color;
1596
1597 if (isIrregularInner && mShowIrregularInnerEdges)
1598 color = getValenceColorCode(valence, !boundary);
1599 else if (isIrregularOuterValence2 && mShowIrregularOuterValence2Edges)
1600 color = getValenceColorCode(valence, !boundary);
1601 else
1602 color = mDefaultColor;
1603
1604 addColorToBuffer(color, _buffer, pos++);
1605 addColorToBuffer(color, _buffer, pos++);
1606 }
1607 }
1608 else if ( mPrimitiveMode == PM_IRREGULAR_EDGES )
1609 {
1610 OpenVolumeMesh::EdgeIter e_begin(mMesh.edges_begin()), e_end(mMesh.edges_end());
1611 for (OpenVolumeMesh::EdgeIter e_it = e_begin; e_it != e_end; ++e_it)
1612 {
1613 if (mBoundaryOnly && !mMesh.is_boundary(*e_it)) continue;
1614 if (!is_inside(*e_it)) continue;
1615
1616 bool boundary = mMesh.is_boundary(*e_it);
1617 unsigned int valence = mMesh.valence(*e_it);
1618
1619 bool isRegular = ( boundary && valence == 3) || (!boundary && valence == 4);
1620 bool isIrregularInner = ( boundary && valence < 2) || ( boundary && valence > 3) || (!boundary && valence != 4);
1621 bool isIrregularOuterValence2 = ( boundary && valence == 2);
1622
1623 if (isRegular) continue;
1624 if (isIrregularInner && !mShowIrregularInnerEdges) continue;
1625 if (isIrregularOuterValence2 && !mShowIrregularOuterValence2Edges) continue;
1626
1627 ACG::Vec4f color;
1628
1629 if (isIrregularInner && mShowIrregularInnerEdges)
1630 color = getValenceColorCode(valence, !boundary);
1631 else if (isIrregularOuterValence2 && mShowIrregularOuterValence2Edges)
1632 color = getValenceColorCode(valence, !boundary);
1633 else
1634 color = mDefaultColor;
1635
1636 addColorToBuffer(color, _buffer, pos++);
1637 addColorToBuffer(color, _buffer, pos++);
1638 }
1639 }
1640 else if ((mPrimitiveMode == PM_HALFEDGES) && (mColorMode == CM_HALFEDGE))
1641 {
1642 OpenVolumeMesh::HalfEdgeIter he_begin(mMesh.halfedges_begin()), he_end(mMesh.halfedges_end());
1643 for (OpenVolumeMesh::HalfEdgeIter he_it = he_begin; he_it != he_end; ++he_it)
1644 {
1645 if (mBoundaryOnly && !mMesh.is_boundary(*he_it)) continue;
1646 if (!is_inside(*he_it)) continue;
1647 ACG::Vec4f color = mColorAttrib[*he_it];
1648
1649 addColorToBuffer(color, _buffer, pos++);
1650 addColorToBuffer(color, _buffer, pos++);
1651 }
1652 }
1653
1654 }
1655
1661 template <class VolumeMesh>
1662 void VolumeMeshBufferManager<VolumeMesh>::buildTexCoordBuffer(unsigned char* _buffer)
1663 {
1664
1665 unsigned int pos = 0;
1666
1667 if (mTexCoordMode == TCM_NONE)
1668 return;
1669
1670 if (mPrimitiveMode == PM_FACES)
1671 {
1672 std::vector<ACG::Vec2f> texCoords;
1673 OpenVolumeMesh::FaceIter f_begin(mMesh.faces_begin()), f_end(mMesh.faces_end());
1674 for (OpenVolumeMesh::FaceIter f_it = f_begin; f_it != f_end; ++f_it)
1675 {
1676 if (mBoundaryOnly && !mMesh.is_boundary(*f_it)) continue;
1677 if (!is_inside(*f_it)) continue;
1678 texCoords.clear();
1679
1680 for (OpenVolumeMesh::HalfFaceVertexIter hfv_it = mMesh.hfv_iter(mMesh.halfface_handle(*f_it,0)); hfv_it; ++hfv_it)
1681 texCoords.push_back(mTexcoordAttrib[*hfv_it]);
1682
1683 for (unsigned int i = 0; i < (texCoords.size()-2); i++)
1684 {
1685 addTexCoordToBuffer(texCoords[0], _buffer, pos++);
1686 addTexCoordToBuffer(texCoords[i+1], _buffer, pos++);
1687 addTexCoordToBuffer(texCoords[i+2], _buffer, pos++);
1688 }
1689 }
1690 }
1691 else if (mPrimitiveMode == PM_HALFFACES)
1692 {
1693 std::vector<ACG::Vec2f> texCoords;
1694 OpenVolumeMesh::HalfFaceIter hf_begin(mMesh.halffaces_begin()), hf_end(mMesh.halffaces_end());
1695 for (OpenVolumeMesh::HalfFaceIter hf_it = hf_begin; hf_it != hf_end; ++hf_it)
1696 {
1697 if (mBoundaryOnly && !mMesh.is_boundary(*hf_it)) continue;
1698 if (!is_inside(*hf_it)) continue;
1699 texCoords.clear();
1700
1701 for (OpenVolumeMesh::HalfFaceVertexIter hfv_it = mMesh.hfv_iter(*hf_it); hfv_it; ++hfv_it)
1702 texCoords.push_back(mTexcoordAttrib[*hfv_it]);
1703
1704 for (unsigned int i = 0; i < (texCoords.size()-2); i++)
1705 {
1706 addTexCoordToBuffer(texCoords[0], _buffer, pos++);
1707 addTexCoordToBuffer(texCoords[i+1], _buffer, pos++);
1708 addTexCoordToBuffer(texCoords[i+2], _buffer, pos++);
1709 }
1710 }
1711 }
1712
1713 }
1714
1723 template <class VolumeMesh>
1724 void VolumeMeshBufferManager<VolumeMesh>::buildPickColorBuffer(ACG::GLState& _state, unsigned int _offset, unsigned char* _buffer)
1725 {
1726 unsigned int pos = 0;
1727
1728 if (mPrimitiveMode == PM_VERTICES)
1729 {
1730 for (unsigned int i = 0; i < mMesh.n_vertices(); ++i)
1731 {
1732 if (mBoundaryOnly && !mMesh.is_boundary(VertexHandle(i))) continue;
1733 if (!is_inside(VertexHandle(i))) continue;
1734 ACG::Vec4uc color = _state.pick_get_name_color(VertexHandle(i).idx() + _offset);
1735 addColorToBuffer(color, _buffer, pos++);
1736 }
1737 }
1738 if (mPrimitiveMode == PM_VERTICES_ON_CELLS)
1739 {
1740 for (unsigned int i = 0; i < mMesh.n_vertices(); ++i) {
1741 ACG::Vec4uc color = _state.pick_get_name_color(VertexHandle(i).idx() + _offset);
1742 unsigned int numOfIncidentCells = getNumOfIncidentCells(VertexHandle(i));
1743 for (unsigned int j = 0; j < numOfIncidentCells; j++)
1744 addColorToBuffer(color, _buffer, pos++);
1745 }
1746 }
1747 else if (mPrimitiveMode == PM_EDGES)
1748 {
1749 OpenVolumeMesh::EdgeIter e_begin(mMesh.edges_begin()), e_end(mMesh.edges_end());
1750 for (OpenVolumeMesh::EdgeIter e_it = e_begin; e_it != e_end; ++e_it)
1751 {
1752 if (mBoundaryOnly && !mMesh.is_boundary(*e_it)) continue;
1753 if (!is_inside(*e_it)) continue;
1754 ACG::Vec4uc color = _state.pick_get_name_color(e_it->idx()+_offset);
1755 addColorToBuffer(color, _buffer, pos++);
1756 addColorToBuffer(color, _buffer, pos++);
1757 }
1758 }
1759 else if (mPrimitiveMode == PM_EDGES_ON_CELLS)
1760 {
1761 OpenVolumeMesh::EdgeIter e_begin(mMesh.edges_begin()), e_end(mMesh.edges_end());
1762 for (OpenVolumeMesh::EdgeIter e_it = e_begin; e_it != e_end; ++e_it)
1763 {
1764 ACG::Vec4uc color = _state.pick_get_name_color(e_it->idx()+_offset);
1765 unsigned int numOfIncidentCells = getNumOfIncidentCells(*e_it);
1766 for (unsigned int i = 0; i < numOfIncidentCells*2;i++)
1767 addColorToBuffer(color, _buffer, pos++);
1768 }
1769 }
1770 else if (mPrimitiveMode == PM_FACES)
1771 {
1772 OpenVolumeMesh::FaceIter f_begin(mMesh.faces_begin()), f_end(mMesh.faces_end());
1773 for (OpenVolumeMesh::FaceIter f_it = f_begin; f_it != f_end; ++f_it)
1774 {
1775 if (mBoundaryOnly && !mMesh.is_boundary(*f_it)) continue;
1776 if (!is_inside(*f_it)) continue;
1777 ACG::Vec4uc color = _state.pick_get_name_color(f_it->idx());
1778
1779 unsigned int numOfVertices = 0;
1780 for (OpenVolumeMesh::HalfFaceVertexIter hfv_it = mMesh.hfv_iter(mMesh.halfface_handle(*f_it,0)); hfv_it; ++hfv_it)
1781 ++numOfVertices;
1782
1783 for (unsigned int i = 0; i < (numOfVertices-2)*3; i++)
1784 addColorToBuffer(color, _buffer, pos++);
1785 }
1786 }
1787 else if (mPrimitiveMode == PM_FACES_ON_CELLS)
1788 {
1789 OpenVolumeMesh::FaceIter f_begin(mMesh.faces_begin()), f_end(mMesh.faces_end());
1790 for (OpenVolumeMesh::FaceIter f_it = f_begin; f_it != f_end; ++f_it)
1791 {
1792 ACG::Vec4uc color = _state.pick_get_name_color(f_it->idx()+_offset);
1793
1794 unsigned int numOfVerticesInHalfface = 0;
1795 for (OpenVolumeMesh::HalfFaceVertexIter hfv_it = mMesh.hfv_iter(mMesh.halfface_handle(*f_it,0)); hfv_it; ++hfv_it)
1796 ++numOfVerticesInHalfface;
1797
1798 for (int i = 0; i < 2; i++)
1799 {
1800 OpenVolumeMesh::CellHandle ch = mMesh.incident_cell(mMesh.halfface_handle(*f_it,i));
1801 if (ch != CellHandle(-1))
1802 {
1803 if (!is_inside(ch)) continue;
1804 for (unsigned int i = 0; i < (numOfVerticesInHalfface-2)*3; i++)
1805 addColorToBuffer(color, _buffer, pos++);
1806 }
1807 }
1808 }
1809 }
1810 else if (mPrimitiveMode == PM_CELLS)
1811 {
1812 OpenVolumeMesh::CellIter c_begin(mMesh.cells_begin()), c_end(mMesh.cells_end());
1813 for (OpenVolumeMesh::CellIter c_it = c_begin; c_it != c_end; ++c_it)
1814 {
1815 if (!is_inside(*c_it)) continue;
1816 ACG::Vec4uc color = _state.pick_get_name_color(c_it->idx()+_offset);
1817 std::vector<HalfFaceHandle> hfs = mMesh.cell(*c_it).halffaces();
1818 for (unsigned int i = 0; i < hfs.size(); ++i)
1819 {
1820 unsigned int numOfVerticesInHalfface = 0;
1821 for (OpenVolumeMesh::HalfFaceVertexIter hfv_it = mMesh.hfv_iter(hfs[i]); hfv_it; ++hfv_it)
1822 ++numOfVerticesInHalfface;
1823
1824 unsigned int numOfDrawnFaces = numOfVerticesInHalfface-2;
1825 for (unsigned int i = 0; i < numOfDrawnFaces*3; i++)
1826 addColorToBuffer(color, _buffer, pos++);
1827 }
1828 }
1829 }
1830 }
1831
1839 template <class VolumeMesh>
1840 GLuint VolumeMeshBufferManager<VolumeMesh>::getBuffer()
1841 {
1842 if ((mBuffer == 0) || optionsChanged() || mInvalidated)
1843 {
1844
1845 if (mBuffer == 0)
1846 ACG::GLState::genBuffers(1, &mBuffer);
1847
1848 calculateVertexDeclaration();
1849
1850 if (optionsChanged())
1851 mNumOfVertices = -1;
1852
1853 unsigned int numOfVertices = getNumOfVertices();
1854
1855 if (getNumOfVertices() > 0)
1856 {
1857
1858 unsigned int bufferSize = mVertexSize * numOfVertices;
1859
1860 ACG::GLState::bindBuffer(GL_ARRAY_BUFFER, mBuffer);
1861 ACG::GLState::bufferData(GL_ARRAY_BUFFER, bufferSize, 0, GL_STATIC_DRAW);
1862
1863 unsigned char* buffer = (unsigned char *) ACG::GLState::mapBuffer(
1864 GL_ARRAY_BUFFER, GL_READ_WRITE);
1865
1866 if (buffer)
1867 {
1868
1869 if (positionsNeedRebuild())
1870 buildVertexBuffer(buffer);
1871 if (normalsNeedRebuild())
1872 buildNormalBuffer(buffer);
1873 if (colorsNeedRebuild())
1874 buildColorBuffer(buffer);
1875 if (texCoordsNeedRebuild())
1876 buildTexCoordBuffer(buffer);
1877
1878
1879 ACG::GLState::unmapBuffer(GL_ARRAY_BUFFER);
1880
1881 ACG::GLState::bindBuffer(GL_ARRAY_BUFFER, 0);
1882
1883 }
1884 else
1885 {
1886 std::cerr << "error while mapping buffer" << std::endl;
1887 }
1888
1889 }
1890
1891 saveOptions();
1892 mInvalidated = false;
1893 mGeometryChanged = false;
1894 mColorsChanged = false;
1895 mNormalsChanged = false;
1896 mTexCoordsChanged = false;
1897
1898 }
1899
1900 return mBuffer;
1901 }
1902
1911 template <class VolumeMesh>
1912 GLuint VolumeMeshBufferManager<VolumeMesh>::getPickBuffer(ACG::GLState &_state, unsigned int _offset)
1913 {
1914 if (_offset != mCurrentPickOffset || _state.pick_current_index() != mGlobalPickOffset)
1915 {
1916 invalidateColors();
1917 mGlobalPickOffset = _state.pick_current_index();
1918 }
1919
1920 if ((mBuffer == 0) || optionsChanged() || mInvalidated)
1921 {
1922 if (mBuffer == 0)
1923 ACG::GLState::genBuffers(1, &mBuffer);
1924
1925 calculateVertexDeclaration();
1926
1927 if (optionsChanged())
1928 mNumOfVertices = -1;
1929
1930 unsigned int numOfVertices = getNumOfVertices();
1931
1932 if (getNumOfVertices() > 0)
1933 {
1934
1935 unsigned int bufferSize = mVertexSize * numOfVertices;
1936
1937 ACG::GLState::bindBuffer(GL_ARRAY_BUFFER, mBuffer);
1938 ACG::GLState::bufferData(GL_ARRAY_BUFFER, bufferSize, 0, GL_STATIC_DRAW);
1939
1940 unsigned char* buffer = (unsigned char *) ACG::GLState::mapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE);
1941
1942 if (buffer)
1943 {
1944
1945 if (positionsNeedRebuild())
1946 buildVertexBuffer(buffer);
1947 if (colorsNeedRebuild())
1948 buildPickColorBuffer(_state, _offset, buffer);
1949
1950 ACG::GLState::unmapBuffer(GL_ARRAY_BUFFER);
1951
1952 ACG::GLState::bindBuffer(GL_ARRAY_BUFFER, 0);
1953
1954 }
1955 else
1956 {
1957 std::cerr << "error while mapping buffer" << std::endl;
1958 }
1959
1960 }
1961
1962 mCurrentPickOffset = _offset;
1963 saveOptions();
1964 mInvalidated = false;
1965 mGeometryChanged = false;
1966 mColorsChanged = false;
1967 mTexCoordsChanged = false;
1968
1969 }
1970
1971 return mBuffer;
1972 }
1973
1977 template <class VolumeMesh>
1978 void VolumeMeshBufferManager<VolumeMesh>::invalidate()
1979 {
1980 invalidateGeometry();
1981 invalidateNormals();
1982 invalidateColors();
1983 }
1984
1988 template <class VolumeMesh>
1989 void VolumeMeshBufferManager<VolumeMesh>::invalidateGeometry()
1990 {
1991 mInvalidated = true;
1992 mNumOfVertices = -1;
1993 mGeometryChanged = true;
1994 mColorsChanged = true;
1995 mTexCoordsChanged = true;
1996 mNormalsChanged = true;
1997 mCogsValid = false;
1998 mCellInsidenessValid = false;
1999 }
2000
2004 template <class VolumeMesh>
2005 void VolumeMeshBufferManager<VolumeMesh>::invalidateColors()
2006 {
2007 mInvalidated = true;
2008 mColorsChanged = true;
2009 }
2010
2014 template <class VolumeMesh>
2015 void VolumeMeshBufferManager<VolumeMesh>::invalidateNormals()
2016 {
2017 mInvalidated = true;
2018 mNormalsChanged = true;
2019 }
2020
2024 template <class VolumeMesh>
2025 void VolumeMeshBufferManager<VolumeMesh>::invalidateTexCoords()
2026 {
2027 mInvalidated = true;
2028 mTexCoordsChanged = true;
2029 }
2030
2036 template <class VolumeMesh>
2037 void VolumeMeshBufferManager<VolumeMesh>::free()
2038 {
2039 if (mBuffer != 0)
2040 ACG::GLState::deleteBuffers(1, &mBuffer);
2041
2042 mBuffer = 0;
2043
2044 invalidate();
2045 }
VolumeMeshBufferManager::getValenceColorCode
ACG::Vec4f getValenceColorCode(unsigned int _valence, bool _inner) const
Returns a color code for irregular edges.
Definition: VolumeMeshBufferManagerT.cc:680
OpenVolumeMesh::ColorAttrib< ACG::Vec4f >
OpenVolumeMesh::VertexCellIter
Definition: Iterators.hh:334
OpenVolumeMesh::EdgeHandle
Definition: OpenVolumeMeshHandle.hh:99
VolumeMeshBufferManager::setOptionsFromDrawMode
void setOptionsFromDrawMode(ACG::SceneGraph::DrawModes::DrawMode _drawMode)
Configures the buffer manager's options from a DrawMode.
Definition: VolumeMeshBufferManagerT.cc:336
VolumeMeshBufferManager::calculateCOGs
void calculateCOGs()
Calculates the center of gravity for all cells.
Definition: VolumeMeshBufferManagerT.cc:951
OpenVolumeMesh::CellHandle
Definition: OpenVolumeMeshHandle.hh:101
ACG
Namespace providing different geometric functions concerning angles.
Definition: DBSCANT.cc:51
OpenVolumeMesh::FaceHandle
Definition: OpenVolumeMeshHandle.hh:100
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
OpenVolumeMesh::StatusAttrib
Definition: StatusAttrib.hh:57
VolumeMeshBufferManager::invalidate
void invalidate()
Invalidates the buffer.
Definition: VolumeMeshBufferManagerT.cc:1978
VolumeMeshBufferManager::clearCutPlanes
void clearCutPlanes()
Removes all cut planes.
Definition: VolumeMeshBufferManagerT.cc:424
VolumeMeshBufferManager::invalidateColors
void invalidateColors()
Invalidates colors.
Definition: VolumeMeshBufferManagerT.cc:2005
VolumeMeshBufferManager::invalidateNormals
void invalidateNormals()
Invalidates normals.
Definition: VolumeMeshBufferManagerT.cc:2015
OpenVolumeMesh::OpenVolumeMeshEdge
Definition: BaseEntities.hh:52
VolumeMeshBufferManager::buildColorBuffer
void buildColorBuffer(unsigned char *_buffer)
Adds all colors to the buffer.
Definition: VolumeMeshBufferManagerT.cc:1398
ACG::GLState::pick_get_name_color
Vec4uc pick_get_name_color(unsigned int _idx)
Definition: GLState.cc:1064
OpenVolumeMesh::HalfFaceIter
Definition: Iterators.hh:902
ACG::VERTEX_USAGE_TEXCOORD
"inTexCoord"
Definition: VertexDeclaration.hh:73
VolumeMeshBufferManager::texCoordsNeedRebuild
bool texCoordsNeedRebuild()
Checks whether texture coordinates need to be rebuild.
Definition: VolumeMeshBufferManagerT.cc:1015
VolumeMeshBufferManager::free
void free()
Deletes the buffers on the GPU.
Definition: VolumeMeshBufferManagerT.cc:2037
VolumeMeshBufferManager::addPositionToBuffer
void addPositionToBuffer(ACG::Vec3d _position, unsigned char *_buffer, unsigned int _offset)
Adds a position to the buffer.
Definition: VolumeMeshBufferManagerT.cc:160
OpenVolumeMesh::VertexIter
Definition: Iterators.hh:686
OpenVolumeMesh::EdgeIter
Definition: Iterators.hh:740
VolumeMeshBufferManager::Plane
Definition: VolumeMeshBufferManager.hh:128
ACG::Vec4f
VectorT< float, 4 > Vec4f
Definition: VectorT.hh:144
ACG::GLState::unmapBuffer
static GLboolean unmapBuffer(GLenum target)
Definition: GLState.cc:2114
VolumeMeshBufferManager::addUCharToBuffer
void addUCharToBuffer(unsigned char _value, unsigned char *&_buffer)
Adds an unsigned char to the buffer.
Definition: VolumeMeshBufferManagerT.cc:143
ACG::Vec3d
VectorT< double, 3 > Vec3d
Definition: VectorT.hh:127
VolumeMeshBufferManager::positionsNeedRebuild
bool positionsNeedRebuild()
Checks whether positions need to be rebuild.
Definition: VolumeMeshBufferManagerT.cc:983
ACG::GLState::mapBuffer
static GLvoid * mapBuffer(GLenum target, GLenum access)
Definition: GLState.cc:2109
VolumeMeshBufferManager
This class creates buffers that can be used to render open volume meshs.
Definition: VolumeMeshBufferManager.hh:69
ACG::GLState
Definition: GLState.hh:220
VolumeMeshBufferManager::addCutPlane
void addCutPlane(const typename VolumeMeshBufferManager< VolumeMesh >::Plane &_p)
Adds a cut plane.
Definition: VolumeMeshBufferManagerT.cc:439
OpenVolumeMesh::HalfEdgeIter
Definition: Iterators.hh:794
VolumeMeshBufferManager::getBuffer
GLuint getBuffer()
Returns the name of the buffer.
Definition: VolumeMeshBufferManagerT.cc:1840
OpenVolumeMesh::CellVertexIter
Definition: Iterators.hh:452
VolumeMeshBufferManager::getNumOfIncidentCells
int getNumOfIncidentCells(OpenVolumeMesh::FaceHandle _fh)
Returns the number of cells that are incident to the given face and also inside w.r.t. all cut planes.
Definition: VolumeMeshBufferManagerT.cc:876
VolumeMeshBufferManager::buildPickColorBuffer
void buildPickColorBuffer(ACG::GLState &_state, unsigned int _offset, unsigned char *_buffer)
Adds all picking colors to the buffer.
Definition: VolumeMeshBufferManagerT.cc:1724
OpenVolumeMesh::HalfFaceHandle
Definition: OpenVolumeMeshHandle.hh:103
VolumeMeshBufferManager::setDefaultColor
void setDefaultColor(ACG::Vec4f _defaultColor)
Sets the default color.
Definition: VolumeMeshBufferManagerT.cc:318
VolumeMeshBufferManager::getPickBuffer
GLuint getPickBuffer(ACG::GLState &_state, unsigned int _offset)
Returns the name of the pick buffer.
Definition: VolumeMeshBufferManagerT.cc:1912
ACG::SceneGraph::DrawModes::DrawMode
Specifies a DrawMode.
Definition: DrawModes.hh:294
VolumeMeshBufferManager::calculateVertexDeclaration
void calculateVertexDeclaration()
Constructs a VertexDeclaration, the size and the offsets for the vertices stored in the buffer...
Definition: VolumeMeshBufferManagerT.cc:256
VolumeMeshBufferManager::addNormalToBuffer
void addNormalToBuffer(ACG::Vec3d _normal, unsigned char *_buffer, unsigned int _offset)
Adds a normal to the buffer.
Definition: VolumeMeshBufferManagerT.cc:221
VolumeMeshBufferManager::addColorToBuffer
void addColorToBuffer(ACG::Vec4uc _color, unsigned char *_buffer, unsigned int _offset)
Adds a color to the buffer.
Definition: VolumeMeshBufferManagerT.cc:179
ACG::GLState::pick_current_index
unsigned int pick_current_index() const
Returns the current color picking index (can be used for caching)
Definition: GLState.cc:1114
VolumeMeshBufferManager::buildVertexBuffer
void buildVertexBuffer(unsigned char *_buffer)
Adds all vertices to the buffer.
Definition: VolumeMeshBufferManagerT.cc:1046
VolumeMeshBufferManager::saveOptions
void saveOptions()
State that the current buffer was built with the current options.
Definition: VolumeMeshBufferManagerT.cc:654
ACG::VERTEX_USAGE_COLOR
"inColor"
Definition: VertexDeclaration.hh:74
OpenVolumeMesh::TexCoordAttrib< ACG::Vec2f >
VolumeMeshBufferManager::countNumOfVertices
void countNumOfVertices()
Counts the number of vertices that need to be stored in the buffer.
Definition: VolumeMeshBufferManagerT.cc:702
OpenMesh::VectorT< float, 4 >
ACG::VERTEX_USAGE_POSITION
"inPosition"
Definition: VertexDeclaration.hh:71
VolumeMeshBufferManager::calculateCellInsideness
void calculateCellInsideness()
Calculates for all cells whether they are inside w.r.t. all cut planes.
Definition: VolumeMeshBufferManagerT.cc:600
VolumeMeshBufferManager::optionsChanged
bool optionsChanged()
Tests whether the options were changed since the last time building the buffer.
Definition: VolumeMeshBufferManagerT.cc:636
VolumeMeshBufferManager::buildTexCoordBuffer
void buildTexCoordBuffer(unsigned char *_buffer)
Adds texture coordinates to the buffer.
Definition: VolumeMeshBufferManagerT.cc:1662
VolumeMeshBufferManager::addTexCoordToBuffer
void addTexCoordToBuffer(ACG::Vec2f _texCoord, unsigned char *_buffer, unsigned int _offset)
Adds a texture coordnate to the buffer.
Definition: VolumeMeshBufferManagerT.cc:240
VolumeMeshBufferManager::getNumOfVertices
unsigned int getNumOfVertices()
Returns the number of vertices stored in the buffer.
Definition: VolumeMeshBufferManagerT.cc:303
VolumeMeshBufferManager::invalidateTexCoords
void invalidateTexCoords()
Invalidates texture coordinates.
Definition: VolumeMeshBufferManagerT.cc:2025
ACG::GLState::deleteBuffers
static void deleteBuffers(GLsizei n, const GLuint *buffers)
Definition: GLState.cc:2105
ACG::GLState::bufferData
static void bufferData(GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage)
Definition: GLState.cc:2100
VolumeMeshBufferManager::addFloatToBuffer
void addFloatToBuffer(float _value, unsigned char *&_buffer)
Adds a float to the buffer.
Definition: VolumeMeshBufferManagerT.cc:121
OpenVolumeMesh::HalfEdgeHandle
Definition: OpenVolumeMeshHandle.hh:102
VolumeMeshBufferManager::invalidateGeometry
void invalidateGeometry()
Invalidates geometry.
Definition: VolumeMeshBufferManagerT.cc:1989
OpenVolumeMesh::FaceIter
Definition: Iterators.hh:848
ACG::GLState::genBuffers
static void genBuffers(GLsizei n, GLuint *buffers)
Definition: GLState.cc:2091
VolumeMeshBufferManager::colorsNeedRebuild
bool colorsNeedRebuild()
Checks whether colors need to be rebuild.
Definition: VolumeMeshBufferManagerT.cc:997
OpenVolumeMesh::VertexHandle
Definition: OpenVolumeMeshHandle.hh:98
OpenVolumeMesh::CellIter
Definition: Iterators.hh:956
VolumeMeshBufferManager::normalsNeedRebuild
bool normalsNeedRebuild()
Checks whether normals need to be rebuild.
Definition: VolumeMeshBufferManagerT.cc:1030
OpenVolumeMesh::HalfEdgeCellIter
Definition: Iterators.hh:390
OpenVolumeMesh::HalfFaceVertexIter
Definition: Iterators.hh:568
VolumeMeshBufferManager::is_inside
bool is_inside(const ACG::Vec3d &_p)
Tests whether the given point is inside w.r.t. all cut planes.
Definition: VolumeMeshBufferManagerT.cc:470
OpenVolumeMesh::NormalAttrib< VolumeMesh >
VolumeMeshBufferManager::buildNormalBuffer
void buildNormalBuffer(unsigned char *_buffer)
Adds all normals to the buffer.
Definition: VolumeMeshBufferManagerT.cc:1260
VolumeMeshBufferManager::getCOG
ACG::Vec3d getCOG(OpenVolumeMesh::CellHandle _ch)
Returns the center of gravity of the given cell.
Definition: VolumeMeshBufferManagerT.cc:935