]> Creatis software - cpPlugins.git/blob - lib/cpExtensions/Visualization/OpenGLMeshMapper.hxx
...
[cpPlugins.git] / lib / cpExtensions / Visualization / OpenGLMeshMapper.hxx
1 #ifndef __CPEXTENSIONS__VISUALIZATION__OPENGLMESHMAPPER__HXX__
2 #define __CPEXTENSIONS__VISUALIZATION__OPENGLMESHMAPPER__HXX__
3
4 #include <algorithm>
5 #include <string>
6
7 #include <vtkCommand.h>
8 #include <vtkImageData.h>
9 #include <vtkOpenGLRenderer.h>
10 #include <vtkProperty.h>
11 #include <vtkRenderWindow.h>
12 #include <vtkTimerLog.h>
13 #include <vtkUnsignedCharArray.h>
14
15 #include <vtkOpenGL.h>
16 #include <vtkOpenGLError.h>
17 #define GL_GLEXT_PROTOTYPES
18 #include <GL/glext.h>
19
20 #ifdef _WIN32
21
22 PFNGLGENBUFFERSARBPROC           pglGenBuffers = 0;
23 PFNGLBINDBUFFERARBPROC           pglBindBuffer = 0;
24 PFNGLBUFFERDATAARBPROC           pglBufferData = 0;
25 PFNGLBUFFERSUBDATAARBPROC        pglBufferSubData = 0;
26 PFNGLDELETEBUFFERSARBPROC        pglDeleteBuffers = 0;
27 PFNGLGETBUFFERPARAMETERIVARBPROC pglGetBufferParameteriv = 0;
28 PFNGLMAPBUFFERARBPROC            pglMapBuffer = 0;
29 PFNGLUNMAPBUFFERARBPROC          pglUnmapBuffer = 0;
30
31 #define glGenBuffers           pglGenBuffers
32 #define glBindBuffer           pglBindBuffer
33 #define glBufferData           pglBufferData
34 #define glBufferSubData        pglBufferSubData
35 #define glDeleteBuffers        pglDeleteBuffers
36 #define glGetBufferParameteriv pglGetBufferParameteriv
37 #define glMapBuffer            pglMapBuffer
38 #define glUnmapBuffer          pglUnmapBuffer
39
40 #endif // _WIN32
41
42 // some definitions for what the polydata has in it
43 #define CPPLUGINS_VTK_PDM_NORMALS            0x0001
44 #define CPPLUGINS_VTK_PDM_COLORS             0x0002
45 #define CPPLUGINS_VTK_PDM_TCOORDS            0x0004
46 #define CPPLUGINS_VTK_PDM_CELL_COLORS        0x0008
47 #define CPPLUGINS_VTK_PDM_CELL_NORMALS       0x0010
48 #define CPPLUGINS_VTK_PDM_POINT_TYPE_FLOAT   0x0020
49 #define CPPLUGINS_VTK_PDM_POINT_TYPE_DOUBLE  0x0040
50 #define CPPLUGINS_VTK_PDM_NORMAL_TYPE_FLOAT  0x0080
51 #define CPPLUGINS_VTK_PDM_NORMAL_TYPE_DOUBLE 0x0100
52 #define CPPLUGINS_VTK_PDM_TCOORD_TYPE_FLOAT  0x0200
53 #define CPPLUGINS_VTK_PDM_TCOORD_TYPE_DOUBLE 0x0400
54 #define CPPLUGINS_VTK_PDM_TCOORD_1D          0x0800
55 #define CPPLUGINS_VTK_PDM_OPAQUE_COLORS      0x1000
56 #define CPPLUGINS_VTK_PDM_USE_FIELD_DATA     0x2000
57
58 // -------------------------------------------------------------------------
59 template< class M >
60 typename cpExtensions::Visualization::OpenGLMeshMapper< M >::
61 Self* cpExtensions::Visualization::OpenGLMeshMapper< M >::
62 New( )
63 {
64   return( new Self( ) );
65 }
66
67 // -------------------------------------------------------------------------
68 template< class M >
69 void cpExtensions::Visualization::OpenGLMeshMapper< M >::
70 RenderPiece( vtkRenderer* aren, vtkActor* act )
71 {
72   vtkOpenGLClearErrorMacro( );
73
74   // Is the renderer correctly initialized?
75   if( aren->GetRenderWindow( )->CheckAbortStatus( ) )
76     return;
77
78   // Get input mesh ( and check it )
79   M* in = this->GetInput( );
80   if( !in )
81   {
82     vtkErrorMacro( << "No input!" );
83     return;
84
85   } // fi
86   unsigned long numPts = in->GetNumberOfPoints( );
87   if( numPts == 0 )
88   {
89     vtkDebugMacro( << "No points!" );
90     return;
91
92   } // fi
93
94   // Update input, if needed
95   this->InvokeEvent( vtkCommand::StartEvent, NULL );
96   if( !this->Static )
97     in->Update( );
98   this->InvokeEvent( vtkCommand::EndEvent, NULL );
99
100   // Update some visualization objects
101   if( !this->LookupTable )
102     this->CreateDefaultLookupTable( );
103   aren->GetRenderWindow( )->MakeCurrent( );
104
105   // Check clipping planes
106   int numClipPlanes = this->GetNumberOfClippingPlanes( );
107   if( numClipPlanes > 6 )
108   {
109     vtkErrorMacro( << "OpenGL has a limit of 6 clipping planes" );
110     numClipPlanes = 6;
111
112   } // fi
113
114   // Add all the clipping planes
115   double eq[ 4 ];
116   GLenum clipPlaneId;
117   for( int i = 0; i < numClipPlanes; i++ )
118   {
119     this->GetClippingPlaneInDataCoords( act->GetMatrix( ), i, eq );
120
121     clipPlaneId = static_cast< GLenum >( GL_CLIP_PLANE0 + i );
122     glEnable( clipPlaneId );
123     glClipPlane( clipPlaneId, eq );
124
125   } // rof
126
127   // Configure opacity
128   this->MapScalars( act->GetProperty( )->GetOpacity( ) );
129
130   // Configure textures
131   if( this->ColorTextureMap )
132   {
133     /* TODO
134        if( !this->InternalColorTexture )
135        {
136        this->InternalColorTexture =
137        vtkSmartPointer< vtkOpenGLTexture >::New( );
138        this->InternalColorTexture->RepeatOff( );
139
140        } // fi
141        this->InternalColorTexture->SetInputData( this->ColorTextureMap );
142     */
143
144     // Keep color from interacting with texture.
145     float info[ 4 ] = { float( 1 ), float( 1 ), float( 1 ), float( 1 ) };
146     glMaterialfv( GL_FRONT_AND_BACK, GL_DIFFUSE, info );
147
148   } // fi
149
150   int noAbort = 1;
151   bool renderNeeded = !this->ImmediateModeRendering;
152   renderNeeded     &= !this->GetGlobalImmediateModeRendering( );
153
154   // Something has changed in the pipeline?
155   if(
156     this->GetMTime( ) > this->BuildTime ||
157     in->GetMTime( ) > this->BuildTime ||
158     act->GetProperty( )->GetMTime( ) > this->BuildTime ||
159     aren->GetRenderWindow( ) != this->LastWindow
160     )
161   {
162     // Update visualization objects
163     this->ReleaseGraphicsResources( aren->GetRenderWindow( ) );
164     this->LastWindow = aren->GetRenderWindow( );
165
166     if( renderNeeded )
167     {
168       // Load textures
169       /* TODO
170          if( this->ColorTextureMap )
171          this->InternalColorTexture->Load( aren );
172       */
173
174       // Time the actual drawing
175       this->Timer->StartTimer( );
176       noAbort = this->Draw( aren, act );
177       this->Timer->StopTimer( );
178
179     } // fi
180
181     if( noAbort )
182       this->BuildTime.Modified( );
183   }
184   else
185   {
186     // If nothing changed, just draw the mapped mesh
187     if( renderNeeded )
188     {
189       // Load textures
190       /* TODO
191          if( this->ColorTextureMap )
192          this->InternalColorTexture->Load( aren );
193       */
194
195       // Time the actual drawing
196       this->Timer->StartTimer( );
197       this->Draw( aren, act );
198       this->Timer->StopTimer( );
199
200     } // fi
201
202   } // fi
203
204   // if we are in immediate mode rendering we always
205   // want to draw the primitives here
206   if( !renderNeeded )
207   {
208     // Load textures
209     /* TODO
210        if( this->ColorTextureMap )
211        this->InternalColorTexture->Load( aren );
212     */
213
214     // Time the actual drawing
215     this->Timer->StartTimer( );
216     this->Draw( aren, act );
217     this->Timer->StopTimer( );
218
219   } // fi
220   this->TimeToDraw = this->Timer->GetElapsedTime( );
221
222   // If the timer is not accurate enough, set it to a small
223   // time so that it is not zero
224   if( this->TimeToDraw == double( 0 ) )
225     this->TimeToDraw = double( 1e-3 );
226
227   for( int c = 0; c < numClipPlanes; c++ )
228   {
229     GLenum clipPlaneId = static_cast< GLenum >( GL_CLIP_PLANE0 + c );
230     glDisable( clipPlaneId );
231
232   } // rof
233   vtkOpenGLCheckErrorMacro( "failed after RenderPiece\n" );
234 }
235
236 // -------------------------------------------------------------------------
237 template< class M >
238 void cpExtensions::Visualization::OpenGLMeshMapper< M >::
239 ReleaseGraphicsResources( vtkWindow* win )
240 {
241   if( win && win->GetMapped( ) )
242   {
243     win->MakeCurrent( );
244     vtkOpenGLCheckErrorMacro( "failed after ReleaseGraphicsResources" );
245
246   } // fi
247   this->LastWindow = NULL;
248
249   // TAKEN FROM BASIC vtkOpenGLPolyDataMapper:
250   // We may not want to do this here.
251   /* TODO
252      if( this->InternalColorTexture )
253      this->InternalColorTexture->ReleaseGraphicsResources( win );
254   */
255 }
256
257 // -------------------------------------------------------------------------
258 template< class M >
259 int cpExtensions::Visualization::OpenGLMeshMapper< M >::
260 Draw( vtkRenderer* aren, vtkActor* act )
261 {
262   vtkOpenGLClearErrorMacro( );
263
264   // First and second initialization check
265   if( this->FirstRendering )
266     this->FirstRendering = !( this->_ConfigureOpenGL( ) );
267   if( this->FirstRendering )
268     return( 0 );
269
270   vtkOpenGLRenderer* ren = static_cast< vtkOpenGLRenderer* >( aren );
271   int rep, interpolation;
272   float tran;
273   vtkProperty* prop;
274   vtkUnsignedCharArray* c = NULL;
275   int tDim;
276   int noAbort = 1;
277   M* input = this->GetInput( );
278   int cellScalars = 0;
279   vtkIdType cellNum = 0;
280   int cellNormals;
281   int resolve = 0, zResolve = 0;
282   double zRes = 0.0;
283
284   // get the property
285   prop = act->GetProperty( );
286
287   // get the transparency
288   tran = prop->GetOpacity( );
289
290   // if the primitives are invisable then get out of here
291   if( tran <= 0.0 )
292     return( noAbort );
293
294   // get the representation ( e.g., surface / wireframe / points )
295   rep = prop->GetRepresentation( );
296
297   // get the shading interpolation
298   interpolation = prop->GetInterpolation( );
299
300   // are they cell or point scalars
301   if( this->Colors )
302   {
303     c = this->Colors;
304     if(
305       (
306         this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_DATA ||
307         this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_FIELD_DATA ||
308         this->ScalarMode == VTK_SCALAR_MODE_USE_FIELD_DATA ||
309         !input->GetPointData( )
310         ) &&
311       this->ScalarMode != VTK_SCALAR_MODE_USE_POINT_FIELD_DATA
312       )
313       cellScalars = 1;
314
315   } // fi
316
317   cellNormals = 1;
318
319   // if we are doing vertex colors then set lmcolor to adjust
320   // the current materials ambient and diffuse values using
321   // vertex color commands otherwise tell it not to.
322   glDisable( GL_COLOR_MATERIAL );
323   if( c )
324   {
325     GLenum lmcolorMode;
326     if( this->ScalarMaterialMode == VTK_MATERIALMODE_DEFAULT )
327     {
328       if( prop->GetAmbient( ) > prop->GetDiffuse( ) )
329         lmcolorMode = GL_AMBIENT;
330       else
331         lmcolorMode = GL_DIFFUSE;
332     }
333     else if( this->ScalarMaterialMode == VTK_MATERIALMODE_AMBIENT_AND_DIFFUSE )
334       lmcolorMode = GL_AMBIENT_AND_DIFFUSE;
335     else if( this->ScalarMaterialMode == VTK_MATERIALMODE_AMBIENT )
336       lmcolorMode = GL_AMBIENT;
337     else // if( this->ScalarMaterialMode == VTK_MATERIALMODE_DIFFUSE )
338       lmcolorMode = GL_DIFFUSE;
339     glColorMaterial( GL_FRONT_AND_BACK, lmcolorMode );
340     glEnable( GL_COLOR_MATERIAL );
341
342   } // fi
343
344   unsigned long idx = 0;
345   if( c )
346   {
347     idx |= CPPLUGINS_VTK_PDM_COLORS;
348     if( c->GetName( ) )
349       idx |= CPPLUGINS_VTK_PDM_OPAQUE_COLORS;
350   } // fi
351   if( cellScalars )
352     idx |= CPPLUGINS_VTK_PDM_CELL_COLORS;
353   if( cellNormals )
354     idx |= CPPLUGINS_VTK_PDM_CELL_NORMALS;
355   if( this->ScalarMode == VTK_SCALAR_MODE_USE_FIELD_DATA )
356     idx |= CPPLUGINS_VTK_PDM_USE_FIELD_DATA;
357
358   // store the types in the index
359   if( typeid( typename M::CoordRepType ) == typeid( float ) )
360     idx |= CPPLUGINS_VTK_PDM_POINT_TYPE_FLOAT;
361   else if( typeid( typename M::CoordRepType ) == typeid( double ) )
362     idx |= CPPLUGINS_VTK_PDM_POINT_TYPE_DOUBLE;
363
364   if( typeid( typename M::CoordRepType ) == typeid( float ) )
365     idx |= CPPLUGINS_VTK_PDM_NORMAL_TYPE_FLOAT;
366   else if( typeid( typename M::CoordRepType ) == typeid( double ) )
367     idx |= CPPLUGINS_VTK_PDM_NORMAL_TYPE_DOUBLE;
368
369   if( this->GetResolveCoincidentTopology( ) )
370   {
371     resolve = 1;
372     if( this->GetResolveCoincidentTopology( ) == VTK_RESOLVE_SHIFT_ZBUFFER )
373     {
374       zResolve = 1;
375       zRes = this->GetResolveCoincidentTopologyZShift( );
376     }
377     else
378     {
379 #ifdef GL_VERSION_1_1
380       double f, u;
381       glEnable( GL_POLYGON_OFFSET_FILL );
382       this->GetResolveCoincidentTopologyPolygonOffsetParameters( f, u );
383       glPolygonOffset( f, u );
384 #endif
385     } // fi
386
387   } // fi
388
389   // we need to know the total number of cells so that we can
390   // report progress
391   this->TotalCells = input->GetNumberOfCells( );
392
393   // Actual render
394   if( this->VBOSupported )
395   {
396     glBindBuffer( GL_ARRAY_BUFFER, GLuint( this->VBOID1 ) );
397
398     void* ptr = glMapBuffer( GL_ARRAY_BUFFER, GL_READ_WRITE );
399     if( ptr != NULL )
400     {
401       // Copy source points to OpenGL buffer
402       const TPoint* src =
403         input->GetPoints( )->CastToSTLContainer( ).data( );
404       TPoint* dest = reinterpret_cast< TPoint* >( ptr );
405       if( dest != NULL )
406         std::copy( src, src + input->GetNumberOfPoints( ), dest );
407       glUnmapBuffer( GL_ARRAY_BUFFER );
408
409     } // fi
410
411     std::size_t pSize = input->GetNumberOfPoints( ) * sizeof( TPoint );
412
413     // Bind vertices, normals and indices
414     glNormalPointer( this->ElementValueType, 0, ( void* )( pSize ) );
415     glVertexPointer( 3, this->ElementValueType, 0, 0 );
416     glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, GLuint( this->VBOID2 ) );
417
418     // Prepare to render polygons
419     glEnableClientState( GL_NORMAL_ARRAY );
420     glEnableClientState( GL_VERTEX_ARRAY );
421
422     // Iterate over all input cells
423     unsigned int accum = 0;
424     const TCellsContainer* cells = input->GetCells( );
425     TCellIt cIt = cells->Begin( );
426     for( unsigned int nCell = 0; cIt != cells->End( ); nCell++, cIt++ )
427     {
428       const TCell* cell = cIt.Value( );
429       unsigned int nPoints = this->Sizes[ nCell ];
430
431       // Infere rendering mode
432       GLenum mode;
433       switch( prop->GetRepresentation( ) )
434       {
435       case VTK_SURFACE:
436       {
437         switch( nPoints )
438         {
439         case  1: mode = GL_POINTS;    break;
440         case  2: mode = GL_LINES;     break;
441         case  3: mode = GL_TRIANGLES; break;
442         case  4: mode = GL_QUADS;     break;
443         default: mode = GL_POLYGON;   break;
444         } // hctiws
445         // TODO: GL_LINE_STRIP,
446         // TODO: GL_LINE_LOOP,
447         // TODO: GL_TRIANGLE_STRIP,
448         // TODO: GL_TRIANGLE_FAN,
449         // TODO: GL_QUAD_STRIP,
450       }
451       break;
452       case VTK_WIREFRAME: mode = GL_LINE_LOOP; break;
453       case VTK_POINTS: default: mode = GL_POINTS; break;
454       } // hctiws
455
456       // Actual draw all elements
457       if( nPoints < 3 )
458         glDisable( GL_LIGHTING );
459
460       if( nPoints == 2 && zResolve )
461         glDepthRange( zRes, 1. );
462
463       glDrawElements(
464         mode, nPoints, this->IndexElementType, ( GLuint* )( 0 ) + accum
465         );
466       accum += nPoints;
467
468       if( nPoints < 3 )
469         glEnable( GL_LIGHTING );
470
471     } // rof
472
473     glDisableClientState( GL_VERTEX_ARRAY );
474     glDisableClientState( GL_NORMAL_ARRAY );
475
476     glBindBuffer( GL_ARRAY_BUFFER, 0 );
477     glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
478   }
479   else
480   {
481     std::cout << "Not VBO rendering!!!" << std::endl;
482
483   } // fi
484
485   if( resolve )
486   {
487     if( zResolve )
488       glDepthRange( 0., 1. );
489     else
490     {
491 #ifdef GL_VERSION_1_1
492       glDisable( GL_POLYGON_OFFSET_FILL );
493 #endif
494     } // fi
495
496   } // fi
497   vtkOpenGLCheckErrorMacro( "failed after Draw" );
498   this->UpdateProgress( 1.0 );
499   return( noAbort );
500 }
501
502 // -------------------------------------------------------------------------
503 template< class M >
504 cpExtensions::Visualization::OpenGLMeshMapper< M >::
505 OpenGLMeshMapper( )
506   : Superclass( ),
507     TotalCells( 0 ),
508     FirstRendering( true ),
509     VBOID1( 0 ),
510     VBOID2( 0 )
511 {
512   // Infere index element type
513   switch( sizeof( TIndex ) )
514   {
515   case 1 : this->IndexElementType = GL_UNSIGNED_BYTE;  break;
516   case 2 : this->IndexElementType = GL_UNSIGNED_SHORT; break;
517   case 4 : this->IndexElementType = GL_UNSIGNED_INT;   break;
518   default: this->IndexElementType = GL_UNSIGNED_BYTE;  break;
519   } // hctiws
520
521   // Infere point value type
522   if( typeid( TScalar ) == typeid( float ) )
523     this->ElementValueType = GL_FLOAT;
524   else
525     this->ElementValueType = GL_DOUBLE;
526 }
527
528 // -------------------------------------------------------------------------
529 template< class M >
530 cpExtensions::Visualization::OpenGLMeshMapper< M >::
531 ~OpenGLMeshMapper( )
532 {
533   if( this->LastWindow )
534     this->ReleaseGraphicsResources( this->LastWindow );
535   if( this->VBOSupported )
536   {
537     GLuint id1 = GLuint( this->VBOID1 );
538     GLuint id2 = GLuint( this->VBOID2 );
539     if( id1 != GLuint( 0 ) ) glDeleteBuffers( 1, &id1 );
540     if( id2 != GLuint( 0 ) ) glDeleteBuffers( 1, &id2 );
541     this->VBOID1 = this->VBOID2 = 0;
542
543   } // fi
544 }
545
546 // -------------------------------------------------------------------------
547 template< class M >
548 bool cpExtensions::Visualization::OpenGLMeshMapper< M >::
549 _ConfigureOpenGL( )
550 {
551   M* input = this->GetInput( );
552   if( input == NULL )
553     return( false );
554
555 #ifdef _WIN32
556   // Get pointers to GL functions
557   glGenBuffers = reinterpret_cast< PFNGLGENBUFFERSARBPROC >
558     ( wglGetProcAddress( "glGenBuffers" ) );
559   glBindBuffer = reinterpret_cast< PFNGLBINDBUFFERARBPROC >
560     ( wglGetProcAddress( "glBindBuffer" ) );
561   glBufferData = reinterpret_cast< PFNGLBUFFERDATAARBPROC >
562     ( wglGetProcAddress( "glBufferData" ) );
563   glBufferSubData = reinterpret_cast< PFNGLBUFFERSUBDATAARBPROC >
564     ( wglGetProcAddress( "glBufferSubData" ) );
565   glDeleteBuffers = reinterpret_cast< PFNGLDELETEBUFFERSARBPROC >
566     ( wglGetProcAddress( "glDeleteBuffers" ) );
567   glGetBufferParameteriv =
568     reinterpret_cast< PFNGLGETBUFFERPARAMETERIVARBPROC >
569     ( wglGetProcAddress( "glGetBufferParameteriv" ) );
570   glMapBuffer = reinterpret_cast< PFNGLMAPBUFFERARBPROC >
571     ( wglGetProcAddress( "glMapBuffer" ) );
572   glUnmapBuffer = reinterpret_cast< PFNGLUNMAPBUFFERARBPROC >
573     ( wglGetProcAddress( "glUnmapBuffer" ) );
574
575   // Check once again VBO extension
576   if(
577     glGenBuffers != NULL &&
578     glBindBuffer != NULL &&
579     glBufferData != NULL &&
580     glBufferSubData != NULL &&
581     glMapBuffer != NULL &&
582     glUnmapBuffer != NULL &&
583     glDeleteBuffers != NULL &&
584     glGetBufferParameteriv != NULL
585     )
586     this->VBOSupported = true;
587   else
588     this->VBOSupported = false;
589 #else // _WIN32
590   // Check if VBO ( Vertex Buffer Object ) is supported
591   std::string str = ( const char* )( glGetString( GL_EXTENSIONS ) );
592   this->VBOSupported =
593     ( str.find( "GL_ARB_vertex_buffer_object" ) != std::string::npos );
594 #endif // _WIN32 
595
596   if( this->VBOSupported )
597   {
598     // Create points and normals buffers
599     GLuint id1;
600     std::size_t pSize = input->GetNumberOfPoints( ) * sizeof( TPoint );
601     std::size_t nSize =
602       input->GetPointNormalsContainer( ).size( ) * sizeof( TVector );
603     const TPoint* verts =
604       input->GetPoints( )->CastToSTLContainer( ).data( );
605     const TVector* norms = input->GetPointNormalsContainer( ).data( );
606     glGenBuffers( 1, &id1 );
607     glBindBuffer( GL_ARRAY_BUFFER, id1 );
608     glBufferData( GL_ARRAY_BUFFER, pSize + nSize, 0, GL_STREAM_DRAW );
609     glBufferSubData( GL_ARRAY_BUFFER, 0, pSize, verts );
610     glBufferSubData( GL_ARRAY_BUFFER, pSize, nSize, norms );
611     this->VBOID1 = ( unsigned int )( id1 );
612
613     // Create indices buffer
614     const TCellsContainer* cells = input->GetCells( );
615     if( cells == NULL )
616     {
617       itkExceptionMacro(
618         << "This QuadEdgeMesh does not have any cells!"
619         );
620
621     } // fi
622
623     TCellIt cIt;
624     unsigned int cellPointsCount = 0;
625     this->Sizes.clear( );
626     for( cIt = cells->Begin( ); cIt != cells->End( ); cIt++ )
627     {
628       this->Sizes.push_back( cIt.Value( )->GetNumberOfPoints( ) );
629       cellPointsCount += this->Sizes.back( );
630
631     } // rof
632     this->Indices.resize( cellPointsCount );
633     unsigned int indId = 0;
634     for( cIt = cells->Begin( ); cIt != cells->End( ); cIt++ )
635     {
636       const typename M::TQuadEdgeCell* cell =
637         dynamic_cast< const typename M::TQuadEdgeCell* >( cIt.Value( ) );
638       const typename M::TPrimalEdge* edge =
639         cell->GetEntryPrimalEdge( );
640       typename M::TPrimalEdge::ConstIterator iIt = edge->BeginLnext( );
641       for( ; iIt != edge->EndLnext( ); ++iIt )
642         this->Indices[ indId++ ] = ( *iIt )->GetOrigin( );
643
644     } // fi
645
646     // Attach index buffer to VBO
647     std::size_t iSize = std::size_t( this->Indices.size( ) );
648     iSize            *= sizeof( TIndex );
649     const unsigned int* indices = this->Indices.data( );
650     GLuint id2;
651     glGenBuffers( 1, &id2 );
652     glBindBuffer( GL_ARRAY_BUFFER, id2 );
653     glBufferData( GL_ARRAY_BUFFER, iSize, indices, GL_STATIC_DRAW );
654
655     int bSize;
656     glGetBufferParameteriv( GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &bSize );
657     if( iSize != bSize )
658     {
659       glDeleteBuffers( 1, &id2 );
660       id2 = 0;
661       vtkErrorMacro( << "Data size mismatch with input array" );
662
663     } // fi
664     this->VBOID2 = ( unsigned int )( id2 );
665
666   } // fi
667   return( true );
668 }
669
670 #endif // __CPEXTENSIONS__VISUALIZATION__OPENGLMESHMAPPER__HXX__
671
672 // eof - $RCSfile$