StripProcessorT.cc 33.3 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
/*===========================================================================*\
 *                                                                           *
 *                               OpenMesh                                    *
 *      Copyright (C) 2001-2009 by Computer Graphics Group, RWTH Aachen      *
 *                           www.openmesh.org                                *
 *                                                                           *
 *---------------------------------------------------------------------------* 
 *  This file is part of OpenMesh.                                           *
 *                                                                           *
 *  OpenMesh is free software: you can redistribute it and/or modify         * 
 *  it under the terms of the GNU Lesser General Public License as           *
 *  published by the Free Software Foundation, either version 3 of           *
 *  the License, or (at your option) any later version with the              *
 *  following exceptions:                                                    *
 *                                                                           *
 *  If other files instantiate templates or use macros                       *
 *  or inline functions from this file, or you compile this file and         *
 *  link it with other files to produce an executable, this file does        *
 *  not by itself cause the resulting executable to be covered by the        *
 *  GNU Lesser General Public License. This exception does not however       *
 *  invalidate any other reasons why the executable file might be            *
 *  covered by the GNU Lesser General Public License.                        *
 *                                                                           *
 *  OpenMesh is distributed in the hope that it will be useful,              *
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of           *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            *
 *  GNU Lesser General Public License for more details.                      *
 *                                                                           *
 *  You should have received a copy of the GNU LesserGeneral Public          *
 *  License along with OpenMesh.  If not,                                    *
 *  see <http://www.gnu.org/licenses/>.                                      *
 *                                                                           *
\*===========================================================================*/ 

/*===========================================================================*\
 *                                                                           *             
Jan Möbius's avatar
Jan Möbius committed
37
38
 *   $Revision$                                                         *
 *   $Date$                   *
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
 *                                                                           *
\*===========================================================================*/

//=============================================================================
//
//  CLASS StripProcessorT - IMPLEMENTATION
//
//=============================================================================

#define ACG_STRIP_PROCESSOR_C

//== INCLUDES =================================================================

#include <list>
#include <iostream>

Jan Möbius's avatar
Jan Möbius committed
55
56
#include <OpenMesh/Core/Utils/color_cast.hh>

57
58
59
60
61
62
63
64
65
66
67
//== NAMESPACES ===============================================================


namespace ACG {
namespace SceneGraph {
    
  //== IMPLEMENTATION ==========================================================

template <class Mesh>
StripProcessorT<Mesh>::
StripProcessorT(Mesh& _mesh) :
68
mesh_(_mesh),
69
stripsValid_(false),
70
71
updatePerEdgeBuffers_(true),
updatePerFaceBuffers_(true),
72
73
textureIndexProperty_(-1),
perFaceTextureCoordinateProperty_(-1)
74
{
75
76
77
78
79
80
81
82
83

}

template <class Mesh>
StripProcessorT<Mesh>::
~StripProcessorT() {

}

84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
/*template <class Mesh>
uint
StripProcessorT<Mesh>::getPolyDim() {
    
    typename Mesh::FaceIter f_it, f_end = mesh_.faces_end();
    typename Mesh::FaceVertexIter fv_it;
    uint n = 0;
    
    for(f_it = mesh_.faces_begin(); f_it != f_end; ++f_it) {
        uint count = 0;
        for ( fv_it = mesh_.fv_iter(f_it); fv_it; ++fv_it ) {
            ++count;
        }
        
        if(count > n) n = count;
    }
    
    return n;
}

template <class Mesh>
uint
StripProcessorT<Mesh>::getFaceDimension(FaceHandle _fh) {
    uint count = 0;
    for ( typename Mesh::FaceVertexIter fv_it = mesh_.fv_iter(_fh); fv_it; ++fv_it )
        ++count;
    return count;
}*/

template <class Mesh>
void
StripProcessorT<Mesh>::convexityTest(FaceHandle /*_fh*/) {
}

118
119
120
121
122
template <class Mesh>
unsigned int
StripProcessorT<Mesh>::
stripify()
{
123
124
125
  if ( stripsValid_)
    return nStrips();
  
126
127
128
129
130
131
132
  // preprocess:  add new properties
  mesh_.add_property( processed_ );
  mesh_.add_property( used_ );
  mesh_.request_face_status();

  // build strips
  clear();
Jan Möbius's avatar
Jan Möbius committed
133
  buildStrips();
134
135
136
137
138
139

  // postprocess:  remove properties
  mesh_.remove_property(processed_);
  mesh_.remove_property(used_);
  mesh_.release_face_status();

140
141
  stripsValid_ = true;
  
Jan Möbius's avatar
Jan Möbius committed
142
  return nStrips();
143
144
145
146
147
148
149
150
}


//-----------------------------------------------------------------------------

template <class Mesh>
void
StripProcessorT<Mesh>::
Jan Möbius's avatar
Jan Möbius committed
151
buildStrips()
152
{
Jan Möbius's avatar
Jan Möbius committed
153
154
155
156
157
158
159
160
161
162
163
164
165
  // init faces to be un-processed and un-used
  // deleted or hidden faces are marked processed
  if (mesh_.has_face_status()) {
    for (typename Mesh::FaceIter f_it=mesh_.faces_begin(); f_it != mesh_.faces_end(); ++f_it)
      if (mesh_.status(f_it).hidden() || mesh_.status(f_it).deleted())
        processed(f_it) = used(f_it) = true;
      else
        processed(f_it) = used(f_it) = false;
  } else {
    for (typename Mesh::FaceIter f_it=mesh_.faces_begin(); f_it != mesh_.faces_end() ; ++f_it)
      processed(f_it) = used(f_it) = false;
  }
  
166
  if ( mesh_.is_trimesh() ) {
167
    buildStripsTriMesh();
168
  } else {
169
    buildStripsPolyMesh();
170
  }
Jan Möbius's avatar
Jan Möbius committed
171
  
172
  // In this case, we have to sort the array to have all strips with the same texture in one block (reduce texture switching)
173
  if ( perFaceTextureIndexAvailable() ) {
174
175
176
    std::sort(strips_.begin(),strips_.end(),&stripTextureCompare);
  }
  
177
178
179
180
181
}

template <class Mesh>
void
StripProcessorT<Mesh>::
182
183
184
185
buildStripsPolyMesh() {
    
    // Note: Limiting number of strips to be built to three, even for n-gons.
    
186
187
188
189
190
191
    std::vector<Strip>                            experiments; // Three strips to be built. Take longest one after all.
    std::vector< typename Mesh::HalfedgeHandle >  h;           // Three halfedges to start from.
    unsigned int                                  best_idx, best_length, length;
    std::vector< FaceHandles >                    faces;       // Lists of faces.
    typename FaceHandles::iterator                fh_it, fh_end;
    typename Mesh::FaceIter                       f_it, f_end=mesh_.faces_end();
192
    
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
    uint k = 0;
    for (f_it=mesh_.faces_begin(); true; ) {

      // find start face
      for (; f_it != f_end; ++f_it)
          if (!processed(f_it)) break;
      
      // stop if all have been processed
      if (f_it == f_end) 
        break; 
              
      // Number of experiments equals number of edges of the face
      experiments.clear();
      experiments.resize( mesh_.valence(f_it) );
      faces.clear();
      faces.resize(mesh_.valence(f_it));
      
      // Store all adjacent halfedges
      h.clear();
      for ( typename Mesh::FaceHalfedgeIter fhalfedge_it(mesh_,f_it); fhalfedge_it; ++fhalfedge_it ) 
        h.push_back( fhalfedge_it.handle() );
      
      // build all strips, take best one
      best_length = best_idx = 0;
      for (unsigned int i = 0; i < mesh_.valence(f_it) ; ++i)
      {
219
        buildStripPolyMesh(h[i], experiments[i], faces[i]);
220
221
222
        if ((length = experiments[i].indexArray.size()) > best_length) {
            best_length = length;
            best_idx    = i;
223
224
        }
        
Jan Möbius's avatar
Jan Möbius committed
225
        // unset the used flag for the following experiments
226
227
228
229
230
231
232
233
234
235
236
237
238
        for (fh_it=faces[i].begin(), fh_end=faces[i].end(); fh_it!=fh_end; ++fh_it)
            used(*fh_it) = false;
      }
      
      // update processed status
      // The processed flag indicates that the whole face has been rendered
      fh_it  = faces[best_idx].begin();
      fh_end = faces[best_idx].end();
      for (; fh_it!=fh_end; ++fh_it)
          processed(*fh_it) = true;
      
      // add best strip to strip-list
      strips_.push_back(experiments[best_idx]);
239
    }
240
241
242
243
244
}

template <class Mesh>
void
StripProcessorT<Mesh>::
Jan Möbius's avatar
Jan Möbius committed
245
buildStripsTriMesh()
246
{    
247
248
249
250
251
252
  Strip                           experiments[3];
  typename Mesh::HalfedgeHandle   h[3];
  unsigned int                    best_idx, best_length, length;
  FaceHandles                     faces[3];
  typename FaceHandles::iterator  fh_it, fh_end;
  typename Mesh::FaceIter         f_it, f_end=mesh_.faces_end();
253
  
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
  for (f_it=mesh_.faces_begin(); true; )
  {
    // find start face
    for (; f_it!=f_end; ++f_it)
      if (!processed(f_it))
        break;
    if (f_it==f_end) break; // stop if all have been processed


    // collect starting halfedges
    h[0] = mesh_.halfedge_handle(f_it.handle());
    h[1] = mesh_.next_halfedge_handle(h[0]);
    h[2] = mesh_.next_halfedge_handle(h[1]);

    // build 3 strips, take best one
    best_length = best_idx = 0;
    for (unsigned int i=0; i<3; ++i)
    {
272
      buildStripTriMesh(h[i], experiments[i], faces[i]);
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
      if ((length = experiments[i].indexArray.size()) > best_length)
      {
        best_length = length;
        best_idx    = i;
      }

      for (fh_it=faces[i].begin(), fh_end=faces[i].end();
           fh_it!=fh_end; ++fh_it)
        used(*fh_it) = false;
    }


    // update processed status
    fh_it  = faces[best_idx].begin();
    fh_end = faces[best_idx].end();
    for (; fh_it!=fh_end; ++fh_it)
      processed(*fh_it) = true;

    // add best strip to strip-list
    strips_.push_back(experiments[best_idx]);
  }
}

296
297
298
299
300
301
302
303
//-----------------------------------------------------------------------------


template <class Mesh>
void
StripProcessorT<Mesh>::
buildStripPolyMesh(typename Mesh::HalfedgeHandle _start_hh,
                  Strip& _strip,
304
                  FaceHandles& _faces) {
305
    
306
307
308
309
    std::list<unsigned int>               strip;
    std::list<typename Mesh::FaceHandle > faceMap;
    typename Mesh::FaceHandle             fh;
    typename Mesh::HalfedgeHandle         hh_left, hh_right; // Keep the hh of the halfedge where we started
310
                      
311
    // reset list
312
313
314
315
    _faces.clear();

    // Init strip
    strip.push_back(mesh_.from_vertex_handle(_start_hh).idx());
316
    strip.push_back(mesh_.to_vertex_handle(_start_hh).idx());
317
    
318
319
320
321
    // Check if we have to take care of textures
    // If this property is not available, we do not have texture info and will therefore 
    // skip texture handling in strip generation
    bool textureHandling = false;
322
    if ( perFaceTextureIndexAvailable() ) {
323
      textureHandling = true;
324
      _strip.textureIndex = mesh_.property(textureIndexProperty_,mesh_.face_handle(_start_hh));
325
    } 
326
327
    
    /// \todo Implement texture processing here
Jan Möbius's avatar
Jan Möbius committed
328

329
330
331
332
333
334
    // Walk along the strip: 1st direction
    // We construct the strip by using alternating vertices
    // of each side.
    hh_left = hh_right = _start_hh;
    
    while(true) {
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
      
      // Go right
      hh_right = mesh_.prev_halfedge_handle(hh_right);
      
      // Add vertex to triangle strip
      strip.push_back(mesh_.from_vertex_handle(hh_right).idx());
      faceMap.push_back(mesh_.face_handle(hh_right));
      
      // Test if we're at the very last halfedge of the polygon
      if(mesh_.to_vertex_handle(mesh_.next_halfedge_handle(hh_left)) == mesh_.from_vertex_handle(hh_right)) {
          
          // Mark face as processed and used
          fh = mesh_.face_handle(hh_left);
          _faces.push_back(fh);
          used(fh) = true;
      
          // Go over to next face via the exit halfedge
          hh_left = hh_right = mesh_.opposite_halfedge_handle(mesh_.next_halfedge_handle(hh_left));
          
354
355
356
          // Test if polygon is convex (only for testing purposes a.t.m.)
          convexityTest(fh);
          
357
358
359
360
          if(mesh_.is_boundary(hh_left)) break;
          fh = mesh_.face_handle(hh_left);
          if (processed(fh) || used(fh)) break;
          
361
362
          // texture check
          if ( textureHandling && ( _strip.textureIndex != mesh_.property(textureIndexProperty_,fh ) ) )  break;
363
364

//           continue;
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
      } 
      
      // Go left
      hh_left = mesh_.next_halfedge_handle(hh_left);
      
      // Add vertex to triangle strip
      strip.push_back(mesh_.to_vertex_handle(hh_left).idx());
      faceMap.push_back(mesh_.face_handle(hh_left));
      
      // Test if we're at the very last halfedge of the polygon
      if(mesh_.to_vertex_handle(mesh_.next_halfedge_handle(hh_left)) == mesh_.from_vertex_handle(hh_right)) {
        // Mark face as processed and used
        fh = mesh_.face_handle(hh_left);
        _faces.push_back(fh);
        used(fh) = true;
380
        
381
382
        // Go over to next face via the exit halfedge
        hh_left = hh_right = mesh_.opposite_halfedge_handle(mesh_.next_halfedge_handle(hh_left));
383
        
384
385
386
        // Test if polygon is convex (only for testing purposes a.t.m.)
        convexityTest(fh);
        
387
388
389
        if(mesh_.is_boundary(hh_left)) break;
        fh = mesh_.face_handle(hh_left);
        if (processed(fh) || used(fh)) break;
390
        
391
392
        // texture check
        if ( textureHandling && ( _strip.textureIndex != mesh_.property(textureIndexProperty_,fh ) ) ) break;
393

394
395
      }
       
396
397
    }
    
Jan Möbius's avatar
Jan Möbius committed
398
399
400
    // Be carefull with the map. As we run in the opposite direction now,
    // we have to finish the map at the end of the strip
    
401
402
403
404
405
    // Walk along the strip: 2nd direction
    // We construct the strip by using alternating vertices
    // of each side.
    hh_left = hh_right = mesh_.opposite_halfedge_handle(_start_hh);
    
406
    bool flip(false);
407
    while(true) {
408
409
410
411
412
413
414
415
416
      // Boundary check as the first might be at the boundary
      if(mesh_.is_boundary(hh_left)) break;

      // Go right
      hh_right = mesh_.prev_halfedge_handle(hh_right);
      
      // Add vertex to triangle strip
      strip.push_front(mesh_.from_vertex_handle(hh_right).idx());
      faceMap.push_front(mesh_.face_handle(hh_right));
417
      flip = !flip;
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
      
      // Test if we're at the very last halfedge of the polygon
      if(mesh_.to_vertex_handle(mesh_.next_halfedge_handle(hh_left)) == mesh_.from_vertex_handle(hh_right)) {
          
        // Mark face as processed and used
        fh = mesh_.face_handle(hh_right);
        _faces.push_back(fh);
        used(fh) = true;
    
        // Go over to next face via the exit halfedge
        hh_left = hh_right = mesh_.opposite_halfedge_handle(mesh_.next_halfedge_handle(hh_left));
    
        if(mesh_.is_boundary(hh_left)) break;
        fh = mesh_.face_handle(hh_left);
        if (processed(fh) || used(fh)) break;
433
        
434
435
436
        // texture check
        if ( textureHandling && ( _strip.textureIndex != mesh_.property(textureIndexProperty_,fh ) ) ) break;
        
437
438
        // Test if polygon is convex (only for testing purposes a.t.m.)
        convexityTest(fh);
439
        
440
//         continue;
441
        
442
443
444
445
446
447
448
449
      }
      
      // Go left
      hh_left = mesh_.next_halfedge_handle(hh_left);
      
      // Add vertex to triangle strip
      strip.push_front( mesh_.to_vertex_handle(hh_left).idx() );
      faceMap.push_front( mesh_.face_handle(hh_left) );
450
      flip = !flip;
451
452
453
      
      // Test if we're at the very last halfedge of the polygon
      if(mesh_.to_vertex_handle(mesh_.next_halfedge_handle(hh_left)) == mesh_.from_vertex_handle(hh_right)) {
454
        
455
456
457
458
459
460
461
462
463
464
465
466
        // Mark face as processed and used
        fh = mesh_.face_handle(hh_right);
        _faces.push_back(fh);
        used(fh) = true;
        
        // Go over to next face via the exit halfedge
        hh_left = hh_right = mesh_.opposite_halfedge_handle(mesh_.next_halfedge_handle(hh_left));
        
        if(mesh_.is_boundary(hh_left)) break;
        fh = mesh_.face_handle(hh_left);
        if (processed(fh) || used(fh)) break;
        
467
468
469
        // texture check
        if ( textureHandling && ( _strip.textureIndex != mesh_.property(textureIndexProperty_,fh ) ) ) break;
        
470
471
472
473
        // Test if polygon is convex (only for testing purposes a.t.m.)
        convexityTest(fh);
      }
     
474
475
    }
    
476
477
478
479
480
    if ( flip ) {
      strip.push_front(strip.front());
      faceMap.push_front(mesh_.face_handle(0));
    }
    
Jan Möbius's avatar
Jan Möbius committed
481
482
483
484
    // Finish the map ( As this is the start of the strip now, this data will be ignored!
    faceMap.push_front(mesh_.face_handle(0));
    faceMap.push_front(mesh_.face_handle(0));    
    
485
486
487
488
    // copy final strip to _strip
    _strip.indexArray.clear();
    _strip.indexArray.reserve(strip.size());
    std::copy(strip.begin(), strip.end(), std::back_inserter(_strip.indexArray));
489
    
490
491
492
    _strip.faceMap.clear();
    _strip.faceMap.reserve(strip.size());
    std::copy(faceMap.begin(), faceMap.end(), std::back_inserter(_strip.faceMap));
493
494
}

495
496
497
498
499
500
501

//-----------------------------------------------------------------------------


template <class Mesh>
void
StripProcessorT<Mesh>::
502
buildStripTriMesh(typename Mesh::HalfedgeHandle _start_hh,
503
            Strip& _strip,
504
            FaceHandles& _faces)
505
{   
506
507
508
  std::list<unsigned int>  strip;
  typename Mesh::HalfedgeHandle   hh;
  typename Mesh::FaceHandle       fh;
509
510
  
  std::list<typename Mesh::FaceHandle > faceMap;
511
512
513
514
515
516
517
518
519
520


  // reset face list
  _faces.clear();


  // init strip
  strip.push_back(mesh_.from_vertex_handle(_start_hh).idx());
  strip.push_back(mesh_.to_vertex_handle(_start_hh).idx());

521
522
523
524
525
  
  // Check if we have to take care of textures
  // If this property is not available, we do not have texture info and will therefore 
  // skip texture handling in strip generation
  bool textureHandling = false;
526
  if ( perFaceTextureIndexAvailable() ) {
527
528
    textureHandling = true;
    _strip.textureIndex = mesh_.property(textureIndexProperty_,mesh_.face_handle(_start_hh));
529
530
531
532
533
  } else {
    // Set to no texture!
    // This is not really necessary but cleans up for debugging
    _strip.textureIndex = 0; 
  }
534
535
  
  /// \todo Implement texture processing here
536
537
538
539
540
541
542
543
544
545
546
547

  // walk along the strip: 1st direction
  hh = mesh_.prev_halfedge_handle(mesh_.opposite_halfedge_handle(_start_hh));
  while (1)
  {
    // go right
    hh = mesh_.next_halfedge_handle(hh);
    hh = mesh_.opposite_halfedge_handle(hh);
    hh = mesh_.next_halfedge_handle(hh);
    if (mesh_.is_boundary(hh)) break;
    fh = mesh_.face_handle(hh);
    if (processed(fh) || used(fh)) break;
548
549
550
551
    
    // texture check
    if ( textureHandling && ( _strip.textureIndex != mesh_.property(textureIndexProperty_,fh ) ) ) break;
    
552
553
554
    _faces.push_back(fh);
    used(fh) = true;
    strip.push_back(mesh_.to_vertex_handle(hh).idx());
555
    faceMap.push_back(mesh_.face_handle(hh));
556
557
558
559
560
561
562

    // go left
    hh = mesh_.opposite_halfedge_handle(hh);
    hh = mesh_.next_halfedge_handle(hh);
    if (mesh_.is_boundary(hh)) break;
    fh = mesh_.face_handle(hh);
    if (processed(fh) || used(fh)) break;
563
564
565
566
    
    // texture check
    if ( textureHandling && ( _strip.textureIndex != mesh_.property(textureIndexProperty_,fh ) ) ) break;
    
567
568
569
    _faces.push_back(fh);
    used(fh) = true;
    strip.push_back(mesh_.to_vertex_handle(hh).idx());
570
    faceMap.push_back(mesh_.face_handle(hh));
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
  }


  // walk along the strip: 2nd direction
  bool flip(false);
  hh = mesh_.prev_halfedge_handle(_start_hh);
  while (1)
  {
    // go right
    hh = mesh_.next_halfedge_handle(hh);
    hh = mesh_.opposite_halfedge_handle(hh);
    hh = mesh_.next_halfedge_handle(hh);
    if (mesh_.is_boundary(hh)) break;
    fh = mesh_.face_handle(hh);
    if (processed(fh) || used(fh)) break;
586
587
588
589
    
    // texture check
    if ( textureHandling && ( _strip.textureIndex != mesh_.property(textureIndexProperty_,fh ) ) ) break;
    
590
591
592
    _faces.push_back(fh);
    used(fh) = true;
    strip.push_front(mesh_.to_vertex_handle(hh).idx());
593
    faceMap.push_front(mesh_.face_handle(hh));
594
595
596
597
598
599
600
601
    flip = true;

    // go left
    hh = mesh_.opposite_halfedge_handle(hh);
    hh = mesh_.next_halfedge_handle(hh);
    if (mesh_.is_boundary(hh)) break;
    fh = mesh_.face_handle(hh);
    if (processed(fh) || used(fh)) break;
602
603
604
605
    
    // texture check
    if ( textureHandling && ( _strip.textureIndex != mesh_.property(textureIndexProperty_,fh ) ) ) break;
    
606
607
608
    _faces.push_back(fh);
    used(fh) = true;
    strip.push_front(mesh_.to_vertex_handle(hh).idx());
609
    faceMap.push_front(mesh_.face_handle(hh));
610
611
612
    flip = false;
  }

613
614
  if (flip) {
    strip.push_front(strip.front());
615
    faceMap.push_front(mesh_.face_handle(0));
616
617
  }
  
618
619
620
621
  // Add two empty faces at the front. They will not be used to render anything as only the third one defines the 
  // face properties in the strip.
  faceMap.push_front(mesh_.face_handle(0));
  faceMap.push_front(mesh_.face_handle(0));
622
623
624
625
626

  // copy final strip to _strip
  _strip.indexArray.clear();
  _strip.indexArray.reserve(strip.size());
  std::copy(strip.begin(), strip.end(), std::back_inserter(_strip.indexArray));
627
  
628
629
630
  _strip.faceMap.clear();
  _strip.faceMap.reserve(strip.size());
  std::copy(faceMap.begin(), faceMap.end(), std::back_inserter(_strip.faceMap));
631
632
}

633
634
635
template <class Mesh>
void
StripProcessorT<Mesh>::
636
updatePickingVertices(ACG::GLState&  _state, uint _offset) {
637
  
638
  unsigned int idx = 0;
639
  
Jan Möbius's avatar
Jan Möbius committed
640
  // Adjust size of the color buffer to the number of vertices in the mesh
641
642
  pickVertexColorBuf_.resize( mesh_.n_vertices() );
  
Jan Möbius's avatar
Jan Möbius committed
643
  // Get the right picking colors from the gl state and add them per vertex to the color buffer
644
645
  typename Mesh::ConstVertexIter v_it(mesh_.vertices_begin()), v_end(mesh_.vertices_end());
  for (; v_it!=v_end; ++v_it, ++idx) 
646
    pickVertexColorBuf_[idx] = _state.pick_get_name_color(idx + _offset);
Jan Möbius's avatar
Jan Möbius committed
647
648
649
650
651
}

template <class Mesh>
void
StripProcessorT<Mesh>::
652
updatePickingEdges(ACG::GLState& _state,  uint _offset ) {
653
654
655
  
  updatePerEdgeBuffers();
  
Jan Möbius's avatar
Jan Möbius committed
656
  pickEdgeColorBuf_.resize(mesh_.n_edges() * 2);
657
  
Jan Möbius's avatar
Jan Möbius committed
658
  
659
  int idx = 0;
Jan Möbius's avatar
Jan Möbius committed
660
661
  
  typename Mesh::ConstEdgeIter  e_it(mesh_.edges_sbegin()), e_end(mesh_.edges_end());
662
663
664
665
666
667
  for (; e_it!=e_end; ++e_it) {
    
    const Vec4uc pickColor =  _state.pick_get_name_color (e_it.handle().idx() + _offset);
    
    pickEdgeColorBuf_[idx]    = pickColor;
    pickEdgeColorBuf_[idx+1]  = pickColor;
668

Jan Möbius's avatar
Jan Möbius committed
669
670
671
    idx += 2;
  }
}
672
    
Jan Möbius's avatar
Jan Möbius committed
673
674
675
676
template <class Mesh>
void
StripProcessorT<Mesh>::
updatePickingFaces(ACG::GLState& _state ) {
677
  
678
679
680
681
682
  // Get total number of triangles
  // Each strip has two vertices more than triangles
  unsigned int n_faces = 0;
  for(StripsIterator it = strips_.begin(); it != strips_.end(); ++it) 
    n_faces += (*it).indexArray.size() - 2;
Jan Möbius's avatar
Jan Möbius committed
683
  
684
685
  // 3 vertices per face.
  pickFaceColorBuf_.resize(n_faces * 3);
Jan Möbius's avatar
Jan Möbius committed
686
  
687
688
  // Index to the current buffer position
  unsigned int bufferIndex = 0;
689
  
690
691
  // Process all strips
  for ( unsigned int i = 0 ; i < strips_.size() ; ++i ) {
692
    
693
694
    // The order of the vertices in the strip is alternating but as the last vertex still defines
    // points to the associated face, we dont need to swap here!
695
    
696
697
698
699
700
701
    // process all faces in the strip
    // The strip contains 2 faces less then number of vertices in the strip.
    // As we need seperate faces during rendering, the strips are splitted into triangles
    // The last vertex of each triangle defines the picking color for the last face.
    // The handles and indices are collected during the strip generation.
    for (unsigned int stripIndex = 2 ; stripIndex <  strips_[ i ].indexArray.size() ; ++stripIndex) {
702
      
703
      // We have to provide a vertex color for each of the vertices as we need flat shading!
704
      const Vec4uc pickColor = _state.pick_get_name_color ( strips_[ i ].faceMap[ stripIndex ].idx() );
705
706
707
      pickFaceColorBuf_[ bufferIndex + 0 ] = pickColor;
      pickFaceColorBuf_[ bufferIndex + 1 ] = pickColor;
      pickFaceColorBuf_[ bufferIndex + 2 ] = pickColor;
708
      
709
      bufferIndex += 3;
710
    }
711
712
  }
  
Jan Möbius's avatar
Jan Möbius committed
713
714
}

715
716
717
718
template <class Mesh>
void
StripProcessorT<Mesh>::
updatePickingAny(ACG::GLState& _state ) {
719
720
721
  // Update strip information if necessary
  stripify();
  
722
723
724
725
726
  updatePickingFaces(_state);
  updatePickingEdges(_state,mesh_.n_faces());
  updatePickingVertices(_state,mesh_.n_faces() + mesh_.n_edges());
}

727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
template <class Mesh>
void
StripProcessorT<Mesh>::
updatePerEdgeBuffers() {
  // Only update buffers if they are invalid
  if (!updatePerEdgeBuffers_) 
    return;
  
  perEdgeVertexBuffer_.resize(mesh_.n_edges() * 2);
  
  if ( mesh_.has_edge_colors() ) {
    perEdgeColorBuffer_.resize(mesh_.n_edges() * 2);
  } else
    perEdgeColorBuffer_.clear();    
  
  unsigned int idx = 0;
  
  typename Mesh::ConstEdgeIter  e_it(mesh_.edges_sbegin()), e_end(mesh_.edges_end());
  for (; e_it!=e_end; ++e_it) {
    
    perEdgeVertexBuffer_[idx]   = mesh_.point(mesh_.to_vertex_handle(mesh_.halfedge_handle(e_it, 0)));
    perEdgeVertexBuffer_[idx+1] = mesh_.point(mesh_.to_vertex_handle(mesh_.halfedge_handle(e_it, 1)));
    
    if (  mesh_.has_edge_colors() ) {
      const Vec4f color = OpenMesh::color_cast<Vec4f>( mesh_.color(e_it) ) ;
      perEdgeColorBuffer_[ idx ]     = color;
      perEdgeColorBuffer_[ idx + 1 ] = color;
    }
    
    idx += 2;
  }
  
  updatePerEdgeBuffers_ = false;
  
}

template <class Mesh>
ACG::Vec3f * 
StripProcessorT<Mesh>::
perEdgeVertexBuffer() { 
  // Force update of the buffers if required
  if (updatePerEdgeBuffers_)
    updatePerEdgeBuffers();
  return &(perEdgeVertexBuffer_)[0]; 
}

template <class Mesh>
ACG::Vec4f * 
StripProcessorT<Mesh>::
perEdgeColorBuffer() { 
  // Force update of the buffers if required
  if (updatePerEdgeBuffers_)
    updatePerEdgeBuffers();
  return &(perEdgeColorBuffer_)[0]; 
}

783
784
785
template <class Mesh>
void
StripProcessorT<Mesh>::
786
updatePerFaceBuffers() {
787
788
  
  stripify();
789
790
791
792

  // Only update buffers if they are invalid
  if (!updatePerFaceBuffers_) 
    return;
793
  
Jan Möbius's avatar
Jan Möbius committed
794
  unsigned int n_faces = 0;
795
796
797
798
799

  // For the polyMeshes we have to count the faces in all strips
  // Each strip has two vertices more than triangles
  for(StripsIterator it = strips_.begin(); it != strips_.end(); ++it) 
    n_faces += (*it).indexArray.size() - 2;
Jan Möbius's avatar
Jan Möbius committed
800
801
  
  // 3 vertices per face.
Jan Möbius's avatar
Jan Möbius committed
802
  perFaceVertexBuffer_.resize(n_faces * 3);
803

Jan Möbius's avatar
Jan Möbius committed
804
805
  // Index to the current buffer position
  unsigned int bufferIndex = 0;
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820

  if ( mesh_.has_face_normals() ) 
    perFaceNormalBuffer_.resize(n_faces * 3);
  else
    perFaceNormalBuffer_.clear();
  
  if ( mesh_.has_face_colors() ) 
    perFaceColorBuffer_.resize(n_faces * 3);
  else
    perFaceColorBuffer_.clear();      
  
  if ( perFaceTextureCoordinateAvailable() ) 
    perFaceTextureCoordArray_.resize(n_faces * 3);
  else
    perFaceTextureCoordArray_.clear();   
821

822
  textureRenderData_.clear();
823
  
Jan Möbius's avatar
Jan Möbius committed
824
  if ( perFaceTextureIndexAvailable() )
825
    textureRenderData_.reserve( strips_.size() );
826
  
827
828
  // Process all strips
  for ( unsigned int i = 0 ; i < strips_.size() ; ++i ) {
Jan Möbius's avatar
Jan Möbius committed
829
    
830
    // Record strip information
Jan Möbius's avatar
Jan Möbius committed
831
    // Or store a simple strip info with texture 0
832
833
834
835
    if ( perFaceTextureIndexAvailable() ) {
      textureRenderData_.push_back( TextureRenderInfo(strips_[i].textureIndex , strips_[ i ].indexArray.size() -2 ,bufferIndex) );
    }
    
836
837
838
839
840
841
842
843
844
845
846
    // The order of the vertices in the strip is alternating so we have to alter the directions as well
    // or we get backfacing triangles although they are frontfacing
    bool swap = true;
    
    // process all faces in the strip
    // The strip contains 2 faces less then number of vertices in the strip.
    // As we need seperate faces during rendering, the strips are splitted into triangles
    // The last vertex of each triangle defines the color and the normal for the last face.
    // Handles and indices are collected during the strip generation.
    for (unsigned int stripIndex = 2 ; stripIndex <  strips_[ i ].indexArray.size() ; ++stripIndex) {
      
847
      if (  mesh_.has_face_normals() ) {
848
        const Vec3d normal = mesh_.normal( strips_[ i ].faceMap[ stripIndex ] );
849
        perFaceNormalBuffer_[ bufferIndex + 0 ] = normal;
850
851
852
        perFaceNormalBuffer_[ bufferIndex + 1 ] = normal;
        perFaceNormalBuffer_[ bufferIndex + 2 ] = normal;
      }
853
    
854
      if (  mesh_.has_face_colors() ) {
855
        const Vec4f color = OpenMesh::color_cast<Vec4f>( mesh_.color( strips_[ i ].faceMap[ stripIndex ] ) );
856
        perFaceColorBuffer_[ bufferIndex + 0 ] = color;
857
858
        perFaceColorBuffer_[ bufferIndex + 1 ] = color;
        perFaceColorBuffer_[ bufferIndex + 2 ] = color;
859
860
      }
    
861
862
863
864
865
      if ( swap ) {
        // Cant render triangle strips as we need one color per face and this means duplicating vertices
        perFaceVertexBuffer_[ bufferIndex + 0 ] = mesh_.point(mesh_.vertex_handle( strips_[ i ].indexArray[ stripIndex - 2 ] ));
        perFaceVertexBuffer_[ bufferIndex + 1 ] = mesh_.point(mesh_.vertex_handle( strips_[ i ].indexArray[ stripIndex - 1 ] ));
        perFaceVertexBuffer_[ bufferIndex + 2 ] = mesh_.point(mesh_.vertex_handle( strips_[ i ].indexArray[ stripIndex - 0 ] ));
866
        
867
        if ( perFaceTextureCoordinateAvailable() ) {
868
          typename Mesh::ConstFaceHalfedgeIter fhe_it(mesh_.cfh_iter(strips_[ i ].faceMap[ stripIndex ]));
869
          
870
871
          for ( ; fhe_it ; ++fhe_it ) {
            typename Mesh::VertexHandle cvh = mesh_.to_vertex_handle(fhe_it);
872
            Vec2f texcoord = mesh_.property(perFaceTextureCoordinateProperty_,fhe_it);
873
	    
874
875
876
877
878
879
880
881
882
            if ( mesh_.vertex_handle( strips_[ i ].indexArray[ stripIndex - 2 ] ) == cvh ) {
              perFaceTextureCoordArray_[ bufferIndex + 0 ]  = texcoord; 
              continue;
            } else if ( mesh_.vertex_handle( strips_[ i ].indexArray[ stripIndex - 1 ] ) == cvh ) {
              perFaceTextureCoordArray_[ bufferIndex + 1 ]  = texcoord; 
              continue;
            } else if ( mesh_.vertex_handle( strips_[ i ].indexArray[ stripIndex - 0 ] ) == cvh ) {
              perFaceTextureCoordArray_[ bufferIndex + 2 ]  = texcoord; 
              continue;
883
884
885
            }
          }
          
886
887
888
889
890
891
892
893
894
895
        }
        
        swap = false;
      } else {
        // Cant render triangle strips as we need one color per face and this means duplicating vertices
        perFaceVertexBuffer_[ bufferIndex + 2 ] = mesh_.point(mesh_.vertex_handle( strips_[ i ].indexArray[ stripIndex - 2 ] ));
        perFaceVertexBuffer_[ bufferIndex + 1 ] = mesh_.point(mesh_.vertex_handle( strips_[ i ].indexArray[ stripIndex - 1 ] ));
        perFaceVertexBuffer_[ bufferIndex + 0 ] = mesh_.point(mesh_.vertex_handle( strips_[ i ].indexArray[ stripIndex - 0 ] ));
        
        if ( perFaceTextureCoordinateAvailable() ) {
896
          typename Mesh::ConstFaceHalfedgeIter fhe_it(mesh_.cfh_iter(strips_[ i ].faceMap[ stripIndex ]));
897
          
898
899
900
          for ( ; fhe_it ; ++fhe_it ) {
            typename Mesh::VertexHandle cvh = mesh_.to_vertex_handle(fhe_it);
            const Vec2f texcoord = mesh_.property(perFaceTextureCoordinateProperty_,fhe_it);
901
            
902
903
904
905
906
907
908
909
910
            if ( mesh_.vertex_handle( strips_[ i ].indexArray[ stripIndex - 2 ] ) == cvh ) {
              perFaceTextureCoordArray_[ bufferIndex + 2 ]  = texcoord; 
              continue;
            } else if ( mesh_.vertex_handle( strips_[ i ].indexArray[ stripIndex - 1 ] ) == cvh ) {
              perFaceTextureCoordArray_[ bufferIndex + 1 ]  = texcoord; 
              continue;
            } else if ( mesh_.vertex_handle( strips_[ i ].indexArray[ stripIndex - 0 ] ) == cvh ) {
              perFaceTextureCoordArray_[ bufferIndex + 0 ]  = texcoord; 
              continue;
911
912
913
            }
          }
          
914
915
        }
        
916
        swap = true;
917
      }
918
919
920
921
      
      bufferIndex += 3;
    }
  } 
922
923
  
  updatePerFaceBuffers_ = false;
924
925
}

926
927
928
929
930

template <class Mesh>
ACG::Vec3f * 
StripProcessorT<Mesh>::
perFaceVertexBuffer() { 
931
  
932
933
934
  // Force update of the buffers if required
  if (updatePerFaceBuffers_)
    updatePerFaceBuffers();
935
  
936
937
938
939
940
941
942
943
944
945
  return &(perFaceVertexBuffer_)[0]; 
};

template <class Mesh>
ACG::Vec3f * 
StripProcessorT<Mesh>::
perFaceNormalBuffer() { 
  // Force update of the buffers if required
  if (updatePerFaceBuffers_)
    updatePerFaceBuffers();
946
  
947
948
949
950
  return &(perFaceNormalBuffer_)[0]; 
};

template <class Mesh>
Jan Möbius's avatar
Jan Möbius committed
951
ACG::Vec4f * 
952
953
954
955
956
957
958
959
960
StripProcessorT<Mesh>::
perFaceColorBuffer() { 
  // Force update of the buffers if required
  if (updatePerFaceBuffers_)
    updatePerFaceBuffers();
  
  return &(perFaceColorBuffer_)[0]; 
};  

961
962
963
template <class Mesh>
void
StripProcessorT<Mesh>::
964
965
966
967
968
969
setPerFaceTextureCoordinatePropertyName( std::string _perFaceTextureCoordinatePropertyName ) {
  
  if ( !mesh_.get_property_handle(perFaceTextureCoordinateProperty_,_perFaceTextureCoordinatePropertyName) )  {
    perFaceTextureCoordinateProperty_.invalidate();
    std::cerr << "StripProcessor: Unable to get per face texture coordinate property named " << _perFaceTextureCoordinatePropertyName << std::endl;
  }
970
  
971
972
973
974
975
976
977
978
  // mark the buffers as invalid as we have a new per face index array
  invalidatePerFaceBuffers();
}

template <class Mesh>
void
StripProcessorT<Mesh>::
setIndexPropertyName( std::string _indexPropertyName ) { 
979
980
981
982
  if ( !mesh_.get_property_handle(textureIndexProperty_,_indexPropertyName) )  {
    textureIndexProperty_.invalidate();
    std::cerr << "StripProcessor: Unable to get per face texture Index property named " << _indexPropertyName << std::endl;
  }
983
  
984
985
986
  // mark strips as invalid ( have to be regenerated to collect texture index information)
  stripsValid_ = false;
  
987
988
989
990
  // mark the buffers as invalid as we have a new per face index array
  invalidatePerFaceBuffers();
};

991
992
993
994
//=============================================================================
} // namespace SceneGraph
} // namespace ACG
//=============================================================================