Developer Documentation
StripProcessorT.cc
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 
67 namespace ACG {
68 namespace SceneGraph {
69 
70  //== IMPLEMENTATION ==========================================================
71 
72 template <class Mesh>
75 mesh_(_mesh),
76 stripsValid_(false),
77 updatePerEdgeBuffers_(true),
78 updatePerHalfedgeBuffers_(true),
79 updatePerFaceBuffers_(true),
80 textureIndexPropertyName_("Not Set"),
81 perFaceTextureCoordinatePropertyName_("Not Set")
82 {
83  mesh_.request_face_normals();
84 }
85 
86 template <class Mesh>
89 
90 }
91 
92 /*template <class Mesh>
93 uint
94 StripProcessorT<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 
112 template <class Mesh>
113 uint
114 StripProcessorT<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 
121 template <class Mesh>
122 void
124 }
125 
126 template <class Mesh>
127 unsigned int
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 
156 template <class Mesh>
157 void
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() ) {
176  } else {
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)
182  std::sort(strips_.begin(),strips_.end(),&stripTextureCompare);
183  }
184 
185 }
186 
187 template <class Mesh>
188 void
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 
250 template <class Mesh>
251 void
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 
311 template <class Mesh>
312 void
314 buildStripPolyMesh(typename Mesh::HalfedgeHandle _start_hh,
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 
512 template <class Mesh>
513 void
515 buildStripTriMesh(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 
646 template <class Mesh>
647 void
649 updatePickingVertices(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 
662 template <class Mesh>
663 void
665 updatePickingEdges(ACG::GLState& _state, uint _offset ) {
666 
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 
686 template <class Mesh>
687 void
690 
691  // Make sure, the face buffers are up to date before generating the picking data!
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 
731 template <class Mesh>
732 void
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 
743 template <class Mesh>
744 void
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 
779 template <class Mesh>
780 ACG::Vec3f *
783  // Force update of the buffers if required
786  return &(perEdgeVertexBuffer_)[0];
787 }
788 
789 template <class Mesh>
790 ACG::Vec4f *
793  // Force update of the buffers if required
796  return &(perEdgeColorBuffer_)[0];
797 }
798 
799 
800 template <class Mesh>
801 void
804  // Only update buffers if they are invalid
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 
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 
833 
834 }
835 
836 template <class Mesh>
837 typename Mesh::Point
839 halfedge_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 
865 template <class Mesh>
866 ACG::Vec3f *
869  // Force update of the buffers if required
872  return &(perHalfedgeVertexBuffer_)[0];
873 }
874 
875 template <class Mesh>
876 ACG::Vec4f *
879  // Force update of the buffers if required
882  return &(perHalfedgeColorBuffer_)[0];
883 }
884 
885 template <class Mesh>
886 void
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
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 
1056 template <class Mesh>
1057 ACG::Vec3f *
1060 
1061  // Force update of the buffers if required
1064 
1065  return &(perFaceVertexBuffer_)[0];
1066 }
1067 
1068 template <class Mesh>
1069 ACG::Vec3f *
1072  // Force update of the buffers if required
1075 
1076  return &(perFaceNormalBuffer_)[0];
1077 }
1078 
1079 template <class Mesh>
1080 ACG::Vec3f *
1083  // Force update of the buffers if required
1086 
1087  return &(perFacePerVertexNormalBuffer_)[0];
1088 }
1089 
1090 template <class Mesh>
1091 ACG::Vec4f *
1094  // Force update of the buffers if required
1097 
1098  return &(perFaceColorBuffer_)[0];
1099 }
1100 
1101 template <class Mesh>
1102 void
1104 setPerFaceTextureCoordinatePropertyName( 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
1118 }
1119 
1120 template <class Mesh>
1121 bool
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 
1135 template <class Mesh>
1136 bool
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 
1149 template <class Mesh>
1150 void
1152 setIndexPropertyName( 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
1169 }
1170 
1171 //=============================================================================
1172 } // namespace SceneGraph
1173 } // namespace ACG
1174 //=============================================================================
ACG::Vec4f * perFaceColorBuffer()
get a pointer to the per face color buffer
void clear()
delete all strips
std::vector< ACG::Vec4f > perEdgeColorBuffer_
Per Edge color buffer.
void buildStripsTriMesh()
This method generates strips for triangle meshes.
void updatePerHalfedgeBuffers()
Update all per edge drawing buffer n The updated buffers are: per edge vertex buffer ( 2 vertices per...
Kernel::FaceHalfedgeIter FaceHalfedgeIter
Circulator.
Definition: PolyMeshT.hh:171
bool stripTextureCompare(const Strip &i, const Strip &j)
Compare function for sorting Strips depending on their texture index.
std::vector< ACG::Vec3f > perFaceVertexBuffer_
Buffer holding vertices for per face rendering.
ACG::Vec3f * perFaceNormalBuffer()
get a pointer to the per face normal buffer
unsigned int nStrips() const
returns number of strips
bool stripsValid_
This flag shows if the strips have to be regenerated.
std::vector< ACG::Vec4uc > pickFaceColorBuf_
Call this function to update the color picking array.
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 updatePerEdgeBuffers()
Update all per edge drawing buffer n The updated buffers are: per edge vertex buffer ( 2 vertices per...
bool updatePerHalfedgeBuffers_
This flag controls if an update is really necessary.
std::vector< ACG::Vec3f > perEdgeVertexBuffer_
Per Edge vertex buffer (glLines)
StripsIterator end() const
Access strips.
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 invalidatePerFaceBuffers()
Update of the buffers.
StripsIterator begin() const
Access strips.
Vec4uc pick_get_name_color(unsigned int _idx)
Kernel::ConstFaceHalfedgeIter ConstFaceHalfedgeIter
Circulator.
Definition: PolyMeshT.hh:181
int textureIndex
This contains the texture index used for rendering this strip.
std::vector< OpenMesh::FaceHandle > faceMap
This map contains for each vertex in the strips a handle to the face it closes.
std::string perFaceTextureCoordinatePropertyName_
Property for the per face texture coordinates.
StripProcessorT(Mesh &_mesh)
Default constructor.
std::vector< ACG::Vec4f > perFaceColorBuffer_
Buffer holding vertices for per face rendering.
static bool is_trimesh()
Determine whether this is a PolyMeshT or TriMeshT ( This function does not check the per face vertex ...
Definition: TriMeshT.hh:110
ACG::Vec4f * perEdgeColorBuffer()
get a pointer to the per edge color buffer
void setIndexPropertyName(std::string _indexPropertyName)
set the name of the property used for texture index specification
bool perFaceTextureCoordinateAvailable()
Check if per Face Texture coordinates are available.
std::vector< ACG::Vec4uc > pickVertexColorBuf_
The color buffer used for vertex picking.
class for managing a single triangle strip.
bool updatePerEdgeBuffers_
This flag controls if an update is really necessary.
ACG::Vec4f * perHalfedgeColorBuffer()
get a pointer to the per edge color buffer
Mesh::Point halfedge_point(const typename Mesh::HalfedgeHandle _heh)
compute halfedge point compute visulization point for halfedge (shifted to interior of face) ...
Kernel::VertexHandle VertexHandle
Handle for referencing the corresponding item.
Definition: PolyMeshT.hh:139
std::vector< ACG::Vec3f > perFacePerVertexNormalBuffer_
Buffer holding vertices for per face rendering.
Namespace providing different geometric functions concerning angles.
Definition: DBSCANT.cc:51
std::vector< TextureRenderInfo > textureRenderData_
Property for the per face texture index.
void updatePickingFaces(ACG::GLState &_state)
Call this function to update the color picking array.
std::string textureIndexPropertyName_
Property for the per face texture index.
bool perFaceTextureIndexAvailable()
Check if textureindicies are available.
void updatePickingVertices(ACG::GLState &_state, uint _offset=0)
void setPerFaceTextureCoordinatePropertyName(std::string _perFaceTextureCoordinatePropertyName)
set the name of the property used for texture coordinate
std::vector< ACG::Vec4uc > pickEdgeColorBuf_
std::vector< ACG::Vec3f > perFaceNormalBuffer_
Buffer holding vertices for per face rendering.
std::vector< typename Mesh::FaceHandle > FaceHandles
This flag shows if the strips have to be regenerated.
std::vector< ACG::Vec3f > perHalfedgeVertexBuffer_
Per Edge vertex buffer (glLines)
ACG::Vec3f * perEdgeVertexBuffer()
get a pointer to the per edge vertex buffer
Kernel::Point Point
Coordinate type.
Definition: PolyMeshT.hh:115
ACG::Vec3f * perFaceVertexBuffer()
get a pointer to the per face vertex buffer
std::vector< ACG::Vec4f > perHalfedgeColorBuffer_
Per Edge color buffer.
ACG::Vec3f * perHalfedgeVertexBuffer()
get a pointer to the per edge vertex buffer
void updatePickingEdges(ACG::GLState &_state, uint _offset=0)
bool updatePerFaceBuffers_
This flag controls if an update is really necessary.
void updatePickingAny(ACG::GLState &_state)
Call this function to update the color picking array.
std::vector< ACG::Vec2f > perFaceTextureCoordArray_
Property for the per face texture index.
ACG::Vec3f * perFacePerVertexNormalBuffer()
get a pointer to the per face per vertex normal buffer
std::vector< unsigned int > indexArray
This array cotains the actual triangle strip used for rendering.
void convexityTest(FaceHandle _fh)
Test whether face is convex.
unsigned int stripify()
Compute triangle strips, returns number of strips.
void buildStrips()
this method does the main work
void updatePerFaceBuffers()
Update all per face buffers.