Developer Documentation
Loading...
Searching...
No Matches
StripProcessorT_impl.hh
1/*===========================================================================*\
2 * *
3 * OpenMesh *
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 * $Date$ *
46 * *
47\*===========================================================================*/
48
49//=============================================================================
50//
51// CLASS StripProcessorT - IMPLEMENTATION
52//
53//=============================================================================
54
55#define ACG_STRIP_PROCESSOR_C
56
57//== INCLUDES =================================================================
58
59#include <list>
60#include <iostream>
61
62#include <OpenMesh/Core/Utils/color_cast.hh>
63
64//== NAMESPACES ===============================================================
65
66
67namespace ACG {
68namespace SceneGraph {
69
70 //== IMPLEMENTATION ==========================================================
71
72template <class Mesh>
74StripProcessorT(Mesh& _mesh) :
75mesh_(_mesh),
76stripsValid_(false),
77updatePerEdgeBuffers_(true),
78updatePerHalfedgeBuffers_(true),
79updatePerFaceBuffers_(true),
80textureIndexPropertyName_("Not Set"),
81perFaceTextureCoordinatePropertyName_("Not Set")
82{
83 mesh_.request_face_normals();
84}
85
86template <class Mesh>
91
92/*template <class Mesh>
93uint
94StripProcessorT<Mesh>::getPolyDim() {
95
96 typename Mesh::FaceIter f_it, f_end = mesh_.faces_end();
97 typename Mesh::FaceVertexIter fv_it;
98 uint n = 0;
99
100 for(f_it = mesh_.faces_begin(); f_it != f_end; ++f_it) {
101 uint count = 0;
102 for ( fv_it = mesh_.fv_iter(f_it); fv_it; ++fv_it ) {
103 ++count;
104 }
105
106 if(count > n) n = count;
107 }
108
109 return n;
110}
111
112template <class Mesh>
113uint
114StripProcessorT<Mesh>::getFaceDimension(FaceHandle _fh) {
115 uint count = 0;
116 for ( typename Mesh::FaceVertexIter fv_it = mesh_.fv_iter(_fh); fv_it; ++fv_it )
117 ++count;
118 return count;
119}*/
120
121template <class Mesh>
122void
124}
125
126template <class Mesh>
127unsigned int
129stripify()
130{
131 if ( stripsValid_)
132 return nStrips();
133
134 // preprocess: add new properties
135 mesh_.add_property( processed_ );
136 mesh_.add_property( used_ );
137 mesh_.request_face_status();
138
139 // build strips
140 clear();
141 buildStrips();
142
143 // postprocess: remove properties
144 mesh_.remove_property(processed_);
145 mesh_.remove_property(used_);
146 mesh_.release_face_status();
147
148 stripsValid_ = true;
149
150 return nStrips();
151}
152
153
154//-----------------------------------------------------------------------------
155
156template <class Mesh>
157void
160{
161 // init faces to be un-processed and un-used
162 // deleted or hidden faces are marked processed
163 if (mesh_.has_face_status()) {
164 for (typename Mesh::FaceIter f_it=mesh_.faces_begin(); f_it != mesh_.faces_end(); ++f_it)
165 if (mesh_.status(f_it).hidden() || mesh_.status(f_it).deleted())
166 processed(f_it) = used(f_it) = true;
167 else
168 processed(f_it) = used(f_it) = false;
169 } else {
170 for (typename Mesh::FaceIter f_it=mesh_.faces_begin(); f_it != mesh_.faces_end() ; ++f_it)
171 processed(f_it) = used(f_it) = false;
172 }
173
174 if ( mesh_.is_trimesh() ) {
175 buildStripsTriMesh();
176 } else {
177 buildStripsPolyMesh();
178 }
179
180 // In this case, we have to sort the array to have all strips with the same texture in one block (reduce texture switching)
181 if ( perFaceTextureIndexAvailable() ) {
182 std::sort(strips_.begin(),strips_.end(),&stripTextureCompare);
183 }
184
185}
186
187template <class Mesh>
188void
191
192 // Note: Limiting number of strips to be built to three, even for n-gons.
193
194 std::vector<Strip> experiments; // Three strips to be built. Take longest one after all.
195 std::vector< typename Mesh::HalfedgeHandle > h; // Three halfedges to start from.
196 std::vector< FaceHandles > faces; // Lists of faces.
197 typename FaceHandles::iterator fh_it, fh_end;
198 typename Mesh::FaceIter f_it, f_end=mesh_.faces_end();
199
200 for (f_it=mesh_.faces_begin(); true; ) {
201
202 // find start face
203 for (; f_it != f_end; ++f_it)
204 if (!processed(f_it)) break;
205
206 // stop if all have been processed
207 if (f_it == f_end)
208 break;
209
210 // Number of experiments equals number of edges of the face
211 experiments.clear();
212 experiments.resize( mesh_.valence(f_it) );
213 faces.clear();
214 faces.resize(mesh_.valence(f_it));
215
216 // Store all adjacent halfedges
217 h.clear();
218 for ( typename Mesh::FaceHalfedgeIter fhalfedge_it(mesh_,f_it); fhalfedge_it; ++fhalfedge_it )
219 h.push_back( fhalfedge_it.handle() );
220
221 // build all strips, take best one
222 unsigned int best_length = 0;
223 unsigned int best_idx = 0;
224 for (unsigned int i = 0; i < mesh_.valence(f_it) ; ++i)
225 {
226 buildStripPolyMesh(h[i], experiments[i], faces[i]);
227 const unsigned int length = experiments[i].indexArray.size();
228 if (length > best_length) {
229 best_length = length;
230 best_idx = i;
231 }
232
233 // unset the used flag for the following experiments
234 for (fh_it=faces[i].begin(), fh_end=faces[i].end(); fh_it!=fh_end; ++fh_it)
235 used(*fh_it) = false;
236 }
237
238 // update processed status
239 // The processed flag indicates that the whole face has been rendered
240 fh_it = faces[best_idx].begin();
241 fh_end = faces[best_idx].end();
242 for (; fh_it!=fh_end; ++fh_it)
243 processed(*fh_it) = true;
244
245 // add best strip to strip-list
246 strips_.push_back(experiments[best_idx]);
247 }
248}
249
250template <class Mesh>
251void
254{
255 Strip experiments[3];
256 typename Mesh::HalfedgeHandle h[3];
257
258 FaceHandles faces[3];
259 typename FaceHandles::iterator fh_it, fh_end;
260 typename Mesh::FaceIter f_it, f_end=mesh_.faces_end();
261
262 for (f_it=mesh_.faces_begin(); true; )
263 {
264 // find start face
265 for (; f_it!=f_end; ++f_it)
266 if (!processed(f_it))
267 break;
268 if (f_it==f_end) break; // stop if all have been processed
269
270
271 // collect starting halfedges
272 h[0] = mesh_.halfedge_handle(f_it.handle());
273 h[1] = mesh_.next_halfedge_handle(h[0]);
274 h[2] = mesh_.next_halfedge_handle(h[1]);
275
276 // build 3 strips, take best one
277 unsigned int best_length = 0;
278 unsigned int best_idx = 0;
279
280 for (unsigned int i=0; i<3; ++i)
281 {
282 buildStripTriMesh(h[i], experiments[i], faces[i]);
283
284 const unsigned int length = experiments[i].indexArray.size();
285 if ( length > best_length)
286 {
287 best_length = length;
288 best_idx = i;
289 }
290
291 for (fh_it=faces[i].begin(), fh_end=faces[i].end();
292 fh_it!=fh_end; ++fh_it)
293 used(*fh_it) = false;
294 }
295
296
297 // update processed status
298 fh_it = faces[best_idx].begin();
299 fh_end = faces[best_idx].end();
300 for (; fh_it!=fh_end; ++fh_it)
301 processed(*fh_it) = true;
302
303 // add best strip to strip-list
304 strips_.push_back(experiments[best_idx]);
305 }
306}
307
308//-----------------------------------------------------------------------------
309
310
311template <class Mesh>
312void
315 Strip& _strip,
316 FaceHandles& _faces) {
317
318 std::list<unsigned int> strip;
319 std::list<typename Mesh::FaceHandle > faceMap;
320 typename Mesh::FaceHandle fh;
321 typename Mesh::HalfedgeHandle hh_left, hh_right; // Keep the hh of the halfedge where we started
322
323 // reset list
324 _faces.clear();
325
326 // Init strip
327 strip.push_back(mesh_.from_vertex_handle(_start_hh).idx());
328 strip.push_back(mesh_.to_vertex_handle(_start_hh).idx());
329
330 // Check if we have to take care of textures
331 // If this property is not available, we do not have texture info and will therefore
332 // skip texture handling in strip generation
333 OpenMesh::FPropHandleT< int > textureIndexProperty;
334 bool textureHandling = false;
335 if ( mesh_.get_property_handle(textureIndexProperty, textureIndexPropertyName_) ) {
336 textureHandling = true;
337 _strip.textureIndex = mesh_.property(textureIndexProperty,mesh_.face_handle(_start_hh));
338 }
339
341
342 // Walk along the strip: 1st direction
343 // We construct the strip by using alternating vertices
344 // of each side.
345 hh_left = hh_right = _start_hh;
346
347 while(true) {
348
349 // Go right
350 hh_right = mesh_.prev_halfedge_handle(hh_right);
351
352 // Add vertex to triangle strip
353 strip.push_back(mesh_.from_vertex_handle(hh_right).idx());
354 faceMap.push_back(mesh_.face_handle(hh_right));
355
356 // Test if we're at the very last halfedge of the polygon
357 if(mesh_.to_vertex_handle(mesh_.next_halfedge_handle(hh_left)) == mesh_.from_vertex_handle(hh_right)) {
358
359 // Mark face as processed and used
360 fh = mesh_.face_handle(hh_left);
361 _faces.push_back(fh);
362 used(fh) = true;
363
364 // Go over to next face via the exit halfedge
365 hh_left = hh_right = mesh_.opposite_halfedge_handle(mesh_.next_halfedge_handle(hh_left));
366
367 // Test if polygon is convex (only for testing purposes a.t.m.)
368 convexityTest(fh);
369
370 if(mesh_.is_boundary(hh_left)) break;
371 fh = mesh_.face_handle(hh_left);
372 if (processed(fh) || used(fh)) break;
373
374 // texture check
375 if ( textureHandling && ( _strip.textureIndex != mesh_.property(textureIndexProperty,fh ) ) ) break;
376
377// continue;
378 }
379
380 // Go left
381 hh_left = mesh_.next_halfedge_handle(hh_left);
382
383 // Add vertex to triangle strip
384 strip.push_back(mesh_.to_vertex_handle(hh_left).idx());
385 faceMap.push_back(mesh_.face_handle(hh_left));
386
387 // Test if we're at the very last halfedge of the polygon
388 if(mesh_.to_vertex_handle(mesh_.next_halfedge_handle(hh_left)) == mesh_.from_vertex_handle(hh_right)) {
389 // Mark face as processed and used
390 fh = mesh_.face_handle(hh_left);
391 _faces.push_back(fh);
392 used(fh) = true;
393
394 // Go over to next face via the exit halfedge
395 hh_left = hh_right = mesh_.opposite_halfedge_handle(mesh_.next_halfedge_handle(hh_left));
396
397 // Test if polygon is convex (only for testing purposes a.t.m.)
398 convexityTest(fh);
399
400 if(mesh_.is_boundary(hh_left)) break;
401 fh = mesh_.face_handle(hh_left);
402 if (processed(fh) || used(fh)) break;
403
404 // texture check
405 if ( textureHandling && ( _strip.textureIndex != mesh_.property(textureIndexProperty,fh ) ) ) break;
406
407 }
408
409 }
410
411 // Be carefull with the map. As we run in the opposite direction now,
412 // we have to finish the map at the end of the strip
413
414 // Walk along the strip: 2nd direction
415 // We construct the strip by using alternating vertices
416 // of each side.
417 hh_left = hh_right = mesh_.opposite_halfedge_handle(_start_hh);
418
419 bool flip(false);
420 while(true) {
421 // Boundary check as the first might be at the boundary
422 if(mesh_.is_boundary(hh_left)) break;
423
424 // Go right
425 hh_right = mesh_.prev_halfedge_handle(hh_right);
426
427 // Add vertex to triangle strip
428 strip.push_front(mesh_.from_vertex_handle(hh_right).idx());
429 faceMap.push_front(mesh_.face_handle(hh_right));
430 flip = !flip;
431
432 // Test if we're at the very last halfedge of the polygon
433 if(mesh_.to_vertex_handle(mesh_.next_halfedge_handle(hh_left)) == mesh_.from_vertex_handle(hh_right)) {
434
435 // Mark face as processed and used
436 fh = mesh_.face_handle(hh_right);
437 _faces.push_back(fh);
438 used(fh) = true;
439
440 // Go over to next face via the exit halfedge
441 hh_left = hh_right = mesh_.opposite_halfedge_handle(mesh_.next_halfedge_handle(hh_left));
442
443 if(mesh_.is_boundary(hh_left)) break;
444 fh = mesh_.face_handle(hh_left);
445 if (processed(fh) || used(fh)) break;
446
447 // texture check
448 if ( textureHandling && ( _strip.textureIndex != mesh_.property(textureIndexProperty,fh ) ) ) break;
449
450 // Test if polygon is convex (only for testing purposes a.t.m.)
451 convexityTest(fh);
452
453// continue;
454
455 }
456
457 // Go left
458 hh_left = mesh_.next_halfedge_handle(hh_left);
459
460 // Add vertex to triangle strip
461 strip.push_front( mesh_.to_vertex_handle(hh_left).idx() );
462 faceMap.push_front( mesh_.face_handle(hh_left) );
463 flip = !flip;
464
465 // Test if we're at the very last halfedge of the polygon
466 if(mesh_.to_vertex_handle(mesh_.next_halfedge_handle(hh_left)) == mesh_.from_vertex_handle(hh_right)) {
467
468 // Mark face as processed and used
469 fh = mesh_.face_handle(hh_right);
470 _faces.push_back(fh);
471 used(fh) = true;
472
473 // Go over to next face via the exit halfedge
474 hh_left = hh_right = mesh_.opposite_halfedge_handle(mesh_.next_halfedge_handle(hh_left));
475
476 if(mesh_.is_boundary(hh_left)) break;
477 fh = mesh_.face_handle(hh_left);
478 if (processed(fh) || used(fh)) break;
479
480 // texture check
481 if ( textureHandling && ( _strip.textureIndex != mesh_.property(textureIndexProperty,fh ) ) ) break;
482
483 // Test if polygon is convex (only for testing purposes a.t.m.)
484 convexityTest(fh);
485 }
486
487 }
488
489 if ( flip ) {
490 strip.push_front(strip.front());
491 faceMap.push_front(mesh_.face_handle(0));
492 }
493
494 // Finish the map ( As this is the start of the strip now, this data will be ignored!
495 faceMap.push_front(mesh_.face_handle(0));
496 faceMap.push_front(mesh_.face_handle(0));
497
498 // copy final strip to _strip
499 _strip.indexArray.clear();
500 _strip.indexArray.reserve(strip.size());
501 std::copy(strip.begin(), strip.end(), std::back_inserter(_strip.indexArray));
502
503 _strip.faceMap.clear();
504 _strip.faceMap.reserve(strip.size());
505 std::copy(faceMap.begin(), faceMap.end(), std::back_inserter(_strip.faceMap));
506}
507
508
509//-----------------------------------------------------------------------------
510
511
512template <class Mesh>
513void
515buildStripTriMesh(typename Mesh::HalfedgeHandle _start_hh,
516 Strip& _strip,
517 FaceHandles& _faces)
518{
519 std::list<unsigned int> strip;
520 typename Mesh::HalfedgeHandle hh;
521 typename Mesh::FaceHandle fh;
522
523 std::list<typename Mesh::FaceHandle > faceMap;
524
525
526 // reset face list
527 _faces.clear();
528
529
530 // init strip
531 strip.push_back(mesh_.from_vertex_handle(_start_hh).idx());
532 strip.push_back(mesh_.to_vertex_handle(_start_hh).idx());
533
534 // Check if we have to take care of textures
535 // If this property is not available, we do not have texture info and will therefore
536 // skip texture handling in strip generation
537 bool textureHandling = false;
538 OpenMesh::FPropHandleT< int > textureIndexProperty;
539 if ( mesh_.get_property_handle(textureIndexProperty, textureIndexPropertyName_) ) {
540 textureHandling = true;
541 _strip.textureIndex = mesh_.property(textureIndexProperty,mesh_.face_handle(_start_hh));
542 } else {
543 // Set to no texture!
544 // This is not really necessary but cleans up for debugging
545 _strip.textureIndex = 0;
546 }
547
549
550 // walk along the strip: 1st direction
551 hh = mesh_.prev_halfedge_handle(mesh_.opposite_halfedge_handle(_start_hh));
552 while (1)
553 {
554 // go right
555 hh = mesh_.next_halfedge_handle(hh);
556 hh = mesh_.opposite_halfedge_handle(hh);
557 hh = mesh_.next_halfedge_handle(hh);
558 if (mesh_.is_boundary(hh)) break;
559 fh = mesh_.face_handle(hh);
560 if (processed(fh) || used(fh)) break;
561
562 // texture check
563 if ( textureHandling && ( _strip.textureIndex != mesh_.property(textureIndexProperty,fh ) ) ) break;
564
565 _faces.push_back(fh);
566 used(fh) = true;
567 strip.push_back(mesh_.to_vertex_handle(hh).idx());
568 faceMap.push_back(mesh_.face_handle(hh));
569
570 // go left
571 hh = mesh_.opposite_halfedge_handle(hh);
572 hh = mesh_.next_halfedge_handle(hh);
573 if (mesh_.is_boundary(hh)) break;
574 fh = mesh_.face_handle(hh);
575 if (processed(fh) || used(fh)) break;
576
577 // texture check
578 if ( textureHandling && ( _strip.textureIndex != mesh_.property(textureIndexProperty,fh ) ) ) break;
579
580 _faces.push_back(fh);
581 used(fh) = true;
582 strip.push_back(mesh_.to_vertex_handle(hh).idx());
583 faceMap.push_back(mesh_.face_handle(hh));
584 }
585
586
587 // walk along the strip: 2nd direction
588 bool flip(false);
589 hh = mesh_.prev_halfedge_handle(_start_hh);
590 while (1)
591 {
592 // go right
593 hh = mesh_.next_halfedge_handle(hh);
594 hh = mesh_.opposite_halfedge_handle(hh);
595 hh = mesh_.next_halfedge_handle(hh);
596 if (mesh_.is_boundary(hh)) break;
597 fh = mesh_.face_handle(hh);
598 if (processed(fh) || used(fh)) break;
599
600 // texture check
601 if ( textureHandling && ( _strip.textureIndex != mesh_.property(textureIndexProperty,fh ) ) ) break;
602
603 _faces.push_back(fh);
604 used(fh) = true;
605 strip.push_front(mesh_.to_vertex_handle(hh).idx());
606 faceMap.push_front(mesh_.face_handle(hh));
607 flip = true;
608
609 // go left
610 hh = mesh_.opposite_halfedge_handle(hh);
611 hh = mesh_.next_halfedge_handle(hh);
612 if (mesh_.is_boundary(hh)) break;
613 fh = mesh_.face_handle(hh);
614 if (processed(fh) || used(fh)) break;
615
616 // texture check
617 if ( textureHandling && ( _strip.textureIndex != mesh_.property(textureIndexProperty,fh ) ) ) break;
618
619 _faces.push_back(fh);
620 used(fh) = true;
621 strip.push_front(mesh_.to_vertex_handle(hh).idx());
622 faceMap.push_front(mesh_.face_handle(hh));
623 flip = false;
624 }
625
626 if (flip) {
627 strip.push_front(strip.front());
628 faceMap.push_front(mesh_.face_handle(0));
629 }
630
631 // Add two empty faces at the front. They will not be used to render anything as only the third one defines the
632 // face properties in the strip.
633 faceMap.push_front(mesh_.face_handle(0));
634 faceMap.push_front(mesh_.face_handle(0));
635
636 // copy final strip to _strip
637 _strip.indexArray.clear();
638 _strip.indexArray.reserve(strip.size());
639 std::copy(strip.begin(), strip.end(), std::back_inserter(_strip.indexArray));
640
641 _strip.faceMap.clear();
642 _strip.faceMap.reserve(strip.size());
643 std::copy(faceMap.begin(), faceMap.end(), std::back_inserter(_strip.faceMap));
644}
645
646template <class Mesh>
647void
649updatePickingVertices(ACG::GLState& _state, uint _offset) {
650
651 unsigned int idx = 0;
652
653 // Adjust size of the color buffer to the number of vertices in the mesh
654 pickVertexColorBuf_.resize( mesh_.n_vertices() );
655
656 // Get the right picking colors from the gl state and add them per vertex to the color buffer
657 typename Mesh::ConstVertexIter v_it(mesh_.vertices_begin()), v_end(mesh_.vertices_end());
658 for (; v_it!=v_end; ++v_it, ++idx)
659 pickVertexColorBuf_[idx] = _state.pick_get_name_color(idx + _offset);
660}
661
662template <class Mesh>
663void
665updatePickingEdges(ACG::GLState& _state, uint _offset ) {
666
667 updatePerEdgeBuffers();
668
669 pickEdgeColorBuf_.resize(mesh_.n_edges() * 2);
670
671
672 int idx = 0;
673
674 typename Mesh::ConstEdgeIter e_it(mesh_.edges_sbegin()), e_end(mesh_.edges_end());
675 for (; e_it!=e_end; ++e_it) {
676
677 const Vec4uc pickColor = _state.pick_get_name_color (e_it->idx() + _offset);
678
679 pickEdgeColorBuf_[idx] = pickColor;
680 pickEdgeColorBuf_[idx+1] = pickColor;
681
682 idx += 2;
683 }
684}
685
686template <class Mesh>
687void
690
691 // Make sure, the face buffers are up to date before generating the picking data!
692 updatePerFaceBuffers();
693
694 // Get total number of triangles
695 // Each strip has two vertices more than triangles
696 unsigned int n_faces = 0;
697 for(StripsIterator it = strips_.begin(); it != strips_.end(); ++it)
698 n_faces += (*it).indexArray.size() - 2;
699
700 // 3 vertices per face.
701 pickFaceColorBuf_.resize(n_faces * 3);
702
703 // Index to the current buffer position
704 unsigned int bufferIndex = 0;
705
706 // Process all strips
707 for ( unsigned int i = 0 ; i < strips_.size() ; ++i ) {
708
709 // The order of the vertices in the strip is alternating but as the last vertex still defines
710 // points to the associated face, we dont need to swap here!
711
712 // process all faces in the strip
713 // The strip contains 2 faces less then number of vertices in the strip.
714 // As we need seperate faces during rendering, the strips are splitted into triangles
715 // The last vertex of each triangle defines the picking color for the last face.
716 // The handles and indices are collected during the strip generation.
717 for (unsigned int stripIndex = 2 ; stripIndex < strips_[ i ].indexArray.size() ; ++stripIndex) {
718
719 // We have to provide a vertex color for each of the vertices as we need flat shading!
720 const Vec4uc pickColor = _state.pick_get_name_color ( strips_[ i ].faceMap[ stripIndex ].idx() );
721 pickFaceColorBuf_[ bufferIndex + 0 ] = pickColor;
722 pickFaceColorBuf_[ bufferIndex + 1 ] = pickColor;
723 pickFaceColorBuf_[ bufferIndex + 2 ] = pickColor;
724
725 bufferIndex += 3;
726 }
727 }
728
729}
730
731template <class Mesh>
732void
735 // Update strip information if necessary
736 stripify();
737
738 updatePickingFaces(_state);
739 updatePickingEdges(_state,mesh_.n_faces());
740 updatePickingVertices(_state,mesh_.n_faces() + mesh_.n_edges());
741}
742
743template <class Mesh>
744void
747 // Only update buffers if they are invalid
748 if (!updatePerEdgeBuffers_)
749 return;
750
751 perEdgeVertexBuffer_.resize(mesh_.n_edges() * 2);
752
753 if ( mesh_.has_edge_colors() ) {
754 perEdgeColorBuffer_.resize(mesh_.n_edges() * 2);
755 } else
756 perEdgeColorBuffer_.clear();
757
758 unsigned int idx = 0;
759
760 typename Mesh::ConstEdgeIter e_it(mesh_.edges_sbegin()), e_end(mesh_.edges_end());
761 for (; e_it!=e_end; ++e_it) {
762
763 perEdgeVertexBuffer_[idx] = mesh_.point(mesh_.to_vertex_handle(mesh_.halfedge_handle(e_it, 0)));
764 perEdgeVertexBuffer_[idx+1] = mesh_.point(mesh_.to_vertex_handle(mesh_.halfedge_handle(e_it, 1)));
765
766 if ( mesh_.has_edge_colors() ) {
767 const Vec4f color = OpenMesh::color_cast<Vec4f>( mesh_.color(e_it) ) ;
768 perEdgeColorBuffer_[ idx ] = color;
769 perEdgeColorBuffer_[ idx + 1 ] = color;
770 }
771
772 idx += 2;
773 }
774
775 updatePerEdgeBuffers_ = false;
776
777}
778
779template <class Mesh>
780ACG::Vec3f *
783 // Force update of the buffers if required
784 if (updatePerEdgeBuffers_)
785 updatePerEdgeBuffers();
786 return &(perEdgeVertexBuffer_)[0];
787}
788
789template <class Mesh>
790ACG::Vec4f *
793 // Force update of the buffers if required
794 if (updatePerEdgeBuffers_)
795 updatePerEdgeBuffers();
796 return &(perEdgeColorBuffer_)[0];
797}
798
799
800template <class Mesh>
801void
804 // Only update buffers if they are invalid
805 if (!updatePerHalfedgeBuffers_)
806 return;
807
808 perHalfedgeVertexBuffer_.resize(mesh_.n_halfedges() * 2);
809
810 if ( mesh_.has_halfedge_colors() ) {
811 perHalfedgeColorBuffer_.resize(mesh_.n_halfedges() * 2);
812 } else
813 perHalfedgeColorBuffer_.clear();
814
815 unsigned int idx = 0;
816
817 typename Mesh::ConstHalfedgeIter he_it(mesh_.halfedges_sbegin()), he_end(mesh_.halfedges_end());
818 for (; he_it!=he_end; ++he_it) {
819
820 perHalfedgeVertexBuffer_[idx] = halfedge_point(he_it);
821 perHalfedgeVertexBuffer_[idx+1] = halfedge_point(mesh_.prev_halfedge_handle(he_it));
822
823 if ( mesh_.has_halfedge_colors() ) {
824 const Vec4f color = OpenMesh::color_cast<Vec4f>( mesh_.color(he_it) ) ;
825 perHalfedgeColorBuffer_[ idx ] = color;
826 perHalfedgeColorBuffer_[ idx + 1 ] = color;
827 }
828
829 idx += 2;
830 }
831
832 updatePerHalfedgeBuffers_ = false;
833
834}
835
836template <class Mesh>
837typename Mesh::Point
839halfedge_point(const typename Mesh::HalfedgeHandle _heh) {
840
841 typename Mesh::Point p = mesh_.point(mesh_.to_vertex_handle (_heh));
842 typename Mesh::Point pp = mesh_.point(mesh_.from_vertex_handle(_heh));
843 typename Mesh::Point pn = mesh_.point(mesh_.to_vertex_handle(mesh_.next_halfedge_handle(_heh)));
844
845 // typename Mesh::Point n = (p-pp)%(pn-p);
846 typename Mesh::Point fn;
847 if( !mesh_.is_boundary(_heh))
848 fn = mesh_.normal(mesh_.face_handle(_heh));
849 else
850 fn = mesh_.normal(mesh_.face_handle(mesh_.opposite_halfedge_handle(_heh)));
851
852 typename Mesh::Point upd = ((fn%(pn-p)).normalize() + (fn%(p-pp)).normalize()).normalize();
853
854 upd *= ((pn-p).norm()+(p-pp).norm())*0.08;
855
856 return (p+upd);
857
858 // double alpha = 0.1;
859 // // correct weighting for concave triangles (or at concave boundaries)
860 // if( (fn | n) < 0.0) alpha *=-1.0;
861
862 // return (p*(1.0-2.0*alpha) + pp*alpha + pn*alpha);
863}
864
865template <class Mesh>
866ACG::Vec3f *
869 // Force update of the buffers if required
870 if (updatePerHalfedgeBuffers_)
871 updatePerHalfedgeBuffers();
872 return &(perHalfedgeVertexBuffer_)[0];
873}
874
875template <class Mesh>
876ACG::Vec4f *
879 // Force update of the buffers if required
880 if (updatePerHalfedgeBuffers_)
881 updatePerHalfedgeBuffers();
882 return &(perHalfedgeColorBuffer_)[0];
883}
884
885template <class Mesh>
886void
889
890 stripify();
891
892 // Only update buffers if they are invalid
893 if (!updatePerFaceBuffers_)
894 return;
895
896
897 // Get and Recheck property
898 OpenMesh::HPropHandleT< typename Mesh::TexCoord2D > perFaceTextureCoordinateProperty;
899 const bool usePerFaceTextureCoordinateProperty = mesh_.get_property_handle(perFaceTextureCoordinateProperty,perFaceTextureCoordinatePropertyName_);
900
901 const bool usePerFaceTextureIndex = perFaceTextureIndexAvailable();
902
903 unsigned int n_faces = 0;
904
905 // For the polyMeshes we have to count the faces in all strips
906 // Each strip has two vertices more than triangles
907 for(StripsIterator it = strips_.begin(); it != strips_.end(); ++it)
908 n_faces += (*it).indexArray.size() - 2;
909
910 // 3 vertices per face.
911 perFaceVertexBuffer_.resize(n_faces * 3);
912
913 // Index to the current buffer position
914 unsigned int bufferIndex = 0;
915
916 if ( mesh_.has_face_normals() )
917 perFaceNormalBuffer_.resize(n_faces * 3);
918 else
919 perFaceNormalBuffer_.clear();
920
921 if ( mesh_.has_vertex_normals() )
922 perFacePerVertexNormalBuffer_.resize(n_faces * 3);
923 else
924 perFacePerVertexNormalBuffer_.clear();
925
926 if ( mesh_.has_face_colors() )
927 perFaceColorBuffer_.resize(n_faces * 3);
928 else
929 perFaceColorBuffer_.clear();
930
931 if ( usePerFaceTextureCoordinateProperty )
932 perFaceTextureCoordArray_.resize(n_faces * 3);
933 else
934 perFaceTextureCoordArray_.clear();
935
936 textureRenderData_.clear();
937
938 if ( usePerFaceTextureIndex )
939 textureRenderData_.reserve( strips_.size() );
940
941 // Process all strips
942 for ( unsigned int i = 0 ; i < strips_.size() ; ++i ) {
943
944 // Record strip information
945 // Or store a simple strip info with texture 0
946 if ( usePerFaceTextureIndex ) {
947 textureRenderData_.push_back( TextureRenderInfo(strips_[i].textureIndex , strips_[ i ].indexArray.size() -2 ,bufferIndex) );
948 }
949
950 // The order of the vertices in the strip is alternating so we have to alter the directions as well
951 // or we get backfacing triangles although they are frontfacing
952 bool swap = true;
953
954 // process all faces in the strip
955 // The strip contains 2 faces less then number of vertices in the strip.
956 // As we need seperate faces during rendering, the strips are splitted into triangles
957 // The last vertex of each triangle defines the color and the normal for the last face.
958 // Handles and indices are collected during the strip generation.
959 for (unsigned int stripIndex = 2 ; stripIndex < strips_[ i ].indexArray.size() ; ++stripIndex) {
960
961 if ( mesh_.has_face_normals() ) {
962 const Vec3d normal = mesh_.normal( strips_[ i ].faceMap[ stripIndex ] );
963 perFaceNormalBuffer_[ bufferIndex + 0 ] = normal;
964 perFaceNormalBuffer_[ bufferIndex + 1 ] = normal;
965 perFaceNormalBuffer_[ bufferIndex + 2 ] = normal;
966 }
967
968 if ( mesh_.has_face_colors() ) {
969 const Vec4f color = OpenMesh::color_cast<Vec4f>( mesh_.color( strips_[ i ].faceMap[ stripIndex ] ) );
970 perFaceColorBuffer_[ bufferIndex + 0 ] = color;
971 perFaceColorBuffer_[ bufferIndex + 1 ] = color;
972 perFaceColorBuffer_[ bufferIndex + 2 ] = color;
973 }
974
975 if ( swap ) {
976 // Cant render triangle strips as we need one color per face and this means duplicating vertices
977 perFaceVertexBuffer_[ bufferIndex + 0 ] = mesh_.point(mesh_.vertex_handle( strips_[ i ].indexArray[ stripIndex - 2 ] ));
978 perFaceVertexBuffer_[ bufferIndex + 1 ] = mesh_.point(mesh_.vertex_handle( strips_[ i ].indexArray[ stripIndex - 1 ] ));
979 perFaceVertexBuffer_[ bufferIndex + 2 ] = mesh_.point(mesh_.vertex_handle( strips_[ i ].indexArray[ stripIndex - 0 ] ));
980
981 // Get the normals of all vertices at this face
982 if ( mesh_.has_vertex_normals() ) {
983 perFacePerVertexNormalBuffer_[ bufferIndex + 0 ] = mesh_.normal(mesh_.vertex_handle( strips_[ i ].indexArray[ stripIndex - 2 ] ));
984 perFacePerVertexNormalBuffer_[ bufferIndex + 1 ] = mesh_.normal(mesh_.vertex_handle( strips_[ i ].indexArray[ stripIndex - 1 ] ));
985 perFacePerVertexNormalBuffer_[ bufferIndex + 2 ] = mesh_.normal(mesh_.vertex_handle( strips_[ i ].indexArray[ stripIndex - 0 ] ));
986 }
987
988
989 if ( usePerFaceTextureCoordinateProperty ) {
990 typename Mesh::ConstFaceHalfedgeIter fhe_it(mesh_.cfh_iter(strips_[ i ].faceMap[ stripIndex ]));
991
992 for ( ; fhe_it ; ++fhe_it ) {
993 typename Mesh::VertexHandle cvh = mesh_.to_vertex_handle(fhe_it);
994 Vec2f texcoord = mesh_.property(perFaceTextureCoordinateProperty,fhe_it);
995
996 if ( mesh_.vertex_handle( strips_[ i ].indexArray[ stripIndex - 2 ] ) == cvh ) {
997 perFaceTextureCoordArray_[ bufferIndex + 0 ] = texcoord;
998 continue;
999 } else if ( mesh_.vertex_handle( strips_[ i ].indexArray[ stripIndex - 1 ] ) == cvh ) {
1000 perFaceTextureCoordArray_[ bufferIndex + 1 ] = texcoord;
1001 continue;
1002 } else if ( mesh_.vertex_handle( strips_[ i ].indexArray[ stripIndex - 0 ] ) == cvh ) {
1003 perFaceTextureCoordArray_[ bufferIndex + 2 ] = texcoord;
1004 continue;
1005 }
1006 }
1007
1008 }
1009
1010 swap = false;
1011 } else {
1012 // Cant render triangle strips as we need one color per face and this means duplicating vertices
1013 perFaceVertexBuffer_[ bufferIndex + 2 ] = mesh_.point(mesh_.vertex_handle( strips_[ i ].indexArray[ stripIndex - 2 ] ));
1014 perFaceVertexBuffer_[ bufferIndex + 1 ] = mesh_.point(mesh_.vertex_handle( strips_[ i ].indexArray[ stripIndex - 1 ] ));
1015 perFaceVertexBuffer_[ bufferIndex + 0 ] = mesh_.point(mesh_.vertex_handle( strips_[ i ].indexArray[ stripIndex - 0 ] ));
1016
1017 // Get the normals of all vertices at this face
1018 if ( mesh_.has_vertex_normals() ) {
1019 perFacePerVertexNormalBuffer_[ bufferIndex + 2 ] = mesh_.normal(mesh_.vertex_handle( strips_[ i ].indexArray[ stripIndex - 2 ] ));
1020 perFacePerVertexNormalBuffer_[ bufferIndex + 1 ] = mesh_.normal(mesh_.vertex_handle( strips_[ i ].indexArray[ stripIndex - 1 ] ));
1021 perFacePerVertexNormalBuffer_[ bufferIndex + 0 ] = mesh_.normal(mesh_.vertex_handle( strips_[ i ].indexArray[ stripIndex - 0 ] ));
1022 }
1023
1024 if ( usePerFaceTextureCoordinateProperty ) {
1025 typename Mesh::ConstFaceHalfedgeIter fhe_it(mesh_.cfh_iter(strips_[ i ].faceMap[ stripIndex ]));
1026
1027 for ( ; fhe_it ; ++fhe_it ) {
1028 typename Mesh::VertexHandle cvh = mesh_.to_vertex_handle(fhe_it);
1029 const Vec2f texcoord = mesh_.property(perFaceTextureCoordinateProperty,fhe_it);
1030
1031 if ( mesh_.vertex_handle( strips_[ i ].indexArray[ stripIndex - 2 ] ) == cvh ) {
1032 perFaceTextureCoordArray_[ bufferIndex + 2 ] = texcoord;
1033 continue;
1034 } else if ( mesh_.vertex_handle( strips_[ i ].indexArray[ stripIndex - 1 ] ) == cvh ) {
1035 perFaceTextureCoordArray_[ bufferIndex + 1 ] = texcoord;
1036 continue;
1037 } else if ( mesh_.vertex_handle( strips_[ i ].indexArray[ stripIndex - 0 ] ) == cvh ) {
1038 perFaceTextureCoordArray_[ bufferIndex + 0 ] = texcoord;
1039 continue;
1040 }
1041 }
1042
1043 }
1044
1045 swap = true;
1046 }
1047
1048 bufferIndex += 3;
1049 }
1050 }
1051
1052 updatePerFaceBuffers_ = false;
1053}
1054
1055
1056template <class Mesh>
1057ACG::Vec3f *
1060
1061 // Force update of the buffers if required
1062 if (updatePerFaceBuffers_)
1063 updatePerFaceBuffers();
1064
1065 return &(perFaceVertexBuffer_)[0];
1066}
1067
1068template <class Mesh>
1069ACG::Vec3f *
1072 // Force update of the buffers if required
1073 if (updatePerFaceBuffers_)
1074 updatePerFaceBuffers();
1075
1076 return &(perFaceNormalBuffer_)[0];
1077}
1078
1079template <class Mesh>
1080ACG::Vec3f *
1083 // Force update of the buffers if required
1084 if (updatePerFaceBuffers_)
1085 updatePerFaceBuffers();
1086
1087 return &(perFacePerVertexNormalBuffer_)[0];
1088}
1089
1090template <class Mesh>
1091ACG::Vec4f *
1094 // Force update of the buffers if required
1095 if (updatePerFaceBuffers_)
1096 updatePerFaceBuffers();
1097
1098 return &(perFaceColorBuffer_)[0];
1099}
1100
1101template <class Mesh>
1102void
1104setPerFaceTextureCoordinatePropertyName( std::string _perFaceTextureCoordinatePropertyName ) {
1105
1106 // Check if the given property exists
1107 OpenMesh::HPropHandleT< typename Mesh::TexCoord2D > perFaceTextureCoordinateProperty;
1108 if ( !mesh_.get_property_handle(perFaceTextureCoordinateProperty,_perFaceTextureCoordinatePropertyName) ) {
1109 std::cerr << "StripProcessor: Unable to get per face texture coordinate property named " << _perFaceTextureCoordinatePropertyName << std::endl;
1110 return;
1111 }
1112
1113 // Remember the property name
1114 perFaceTextureCoordinatePropertyName_ = _perFaceTextureCoordinatePropertyName;
1115
1116 // mark the buffers as invalid as we have a new per face index array
1117 invalidatePerFaceBuffers();
1118}
1119
1120template <class Mesh>
1121bool
1123
1124 // We really have to recheck, as the property might get lost externally (e.g. on restores of the mesh)
1125 OpenMesh::HPropHandleT< typename Mesh::TexCoord2D > perFaceTextureCoordinateProperty;
1126 if ( !mesh_.get_property_handle(perFaceTextureCoordinateProperty, perFaceTextureCoordinatePropertyName_) ) {
1127 return false;
1128 }
1129
1130 // Property available
1131 return true;
1132
1133}
1134
1135template <class Mesh>
1136bool
1138
1139 // We really have to recheck, as the property might get lost externally (e.g. on restores of the mesh)
1140 OpenMesh::FPropHandleT< int > textureIndexProperty;
1141 if ( !mesh_.get_property_handle(textureIndexProperty, textureIndexPropertyName_) ) {
1142 return false;
1143 }
1144
1145 // Property available
1146 return true;
1147}
1148
1149template <class Mesh>
1150void
1152setIndexPropertyName( std::string _indexPropertyName ) {
1153
1154 // Check if the given property exists
1155 OpenMesh::FPropHandleT< int > textureIndexProperty;
1156 if ( !mesh_.get_property_handle(textureIndexProperty,_indexPropertyName) ) {
1157 std::cerr << "StripProcessor: Unable to get per face texture Index property named " << _indexPropertyName << std::endl;
1158 return;
1159 }
1160
1161 // Remember the property name
1162 textureIndexPropertyName_ = _indexPropertyName;
1163
1164 // mark strips as invalid ( have to be regenerated to collect texture index information)
1165 stripsValid_ = false;
1166
1167 // mark the buffers as invalid as we have a new per face index array
1168 invalidatePerFaceBuffers();
1169}
1170
1171//=============================================================================
1172} // namespace SceneGraph
1173} // namespace ACG
1174//=============================================================================
Vec4uc pick_get_name_color(size_t _idx)
Definition GLState.cc:1068
StripProcessorT(Mesh &_mesh)
Default constructor.
void convexityTest(FaceHandle _fh)
Test whether face is convex.
void updatePerFaceBuffers()
Update all per face buffers.
ACG::Vec3f * perHalfedgeVertexBuffer()
get a pointer to the per edge vertex buffer
void setPerFaceTextureCoordinatePropertyName(std::string _perFaceTextureCoordinatePropertyName)
set the name of the property used for texture coordinate
void updatePickingEdges(ACG::GLState &_state, uint _offset=0)
ACG::Vec3f * perFacePerVertexNormalBuffer()
get a pointer to the per face per vertex normal buffer
std::vector< typename Mesh::FaceHandle > FaceHandles
This flag shows if the strips have to be regenerated.
bool perFaceTextureIndexAvailable()
Check if textureindicies are available.
void updatePickingVertices(ACG::GLState &_state, uint _offset=0)
void updatePerEdgeBuffers()
Update all per edge drawing buffer n The updated buffers are: per edge vertex buffer ( 2 vertices per...
ACG::Vec4f * perHalfedgeColorBuffer()
get a pointer to the per edge color buffer
ACG::Vec3f * perFaceNormalBuffer()
get a pointer to the per face normal buffer
void updatePickingFaces(ACG::GLState &_state)
Call this function to update the color picking array.
bool perFaceTextureCoordinateAvailable()
Check if per Face Texture coordinates are available.
ACG::Vec3f * perEdgeVertexBuffer()
get a pointer to the per edge vertex buffer
void buildStripPolyMesh(typename Mesh::HalfedgeHandle _start_hh, Strip &_strip, FaceHandles &_faces)
build a strip from a given halfedge (in both directions) of a polymesh
void buildStripTriMesh(typename Mesh::HalfedgeHandle _start_hh, Strip &_strip, FaceHandles &_faces)
build a strip from a given halfedge (in both directions) of a triangle mesh
void updatePerHalfedgeBuffers()
Update all per edge drawing buffer n The updated buffers are: per edge vertex buffer ( 2 vertices per...
ACG::Vec3f * perFaceVertexBuffer()
get a pointer to the per face vertex buffer
void setIndexPropertyName(std::string _indexPropertyName)
set the name of the property used for texture index specification
void updatePickingAny(ACG::GLState &_state)
Call this function to update the color picking array.
ACG::Vec4f * perFaceColorBuffer()
get a pointer to the per face color buffer
void buildStripsTriMesh()
This method generates strips for triangle meshes.
ACG::Vec4f * perEdgeColorBuffer()
get a pointer to the per edge color buffer
unsigned int stripify()
Compute triangle strips, returns number of strips.
void buildStrips()
this method does the main work
Mesh::Point halfedge_point(const typename Mesh::HalfedgeHandle _heh)
compute halfedge point compute visulization point for halfedge (shifted to interior of face)
class for managing a single triangle strip.
std::vector< unsigned int > indexArray
This array cotains the actual triangle strip used for rendering.
std::vector< OpenMesh::FaceHandle > faceMap
This map contains for each vertex in the strips a handle to the face it closes.
int textureIndex
This contains the texture index used for rendering this strip.
Kernel::VertexHandle VertexHandle
Handle for referencing the corresponding item.
Definition PolyMeshT.hh:136
Kernel::ConstFaceHalfedgeIter ConstFaceHalfedgeIter
Circulator.
Definition PolyMeshT.hh:178
Kernel::FaceIter FaceIter
Scalar type.
Definition PolyMeshT.hh:146
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
bool stripTextureCompare(const Strip &i, const Strip &j)
Compare function for sorting Strips depending on their texture index.
Namespace providing different geometric functions concerning angles.