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