1 #ifndef __CPPLUGINS__EXTENSIONS__VISUALIZATION__OPENGLMESHMAPPER__HXX__
2 #define __CPPLUGINS__EXTENSIONS__VISUALIZATION__OPENGLMESHMAPPER__HXX__
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>
15 #include <vtkOpenGL.h>
16 #include <vtkOpenGLError.h>
17 #define GL_GLEXT_PROTOTYPES
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;
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
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
58 // -------------------------------------------------------------------------
60 typename cpPlugins::Extensions::Visualization::OpenGLMeshMapper< M >::
61 Self* cpPlugins::Extensions::Visualization::OpenGLMeshMapper< M >::
64 return( new Self( ) );
67 // -------------------------------------------------------------------------
69 void cpPlugins::Extensions::Visualization::OpenGLMeshMapper< M >::
70 RenderPiece( vtkRenderer* aren, vtkActor* act )
72 vtkOpenGLClearErrorMacro( );
74 // Is the renderer correctly initialized?
75 if( aren->GetRenderWindow( )->CheckAbortStatus( ) )
78 // Get input mesh ( and check it )
79 M* in = this->GetInput( );
82 vtkErrorMacro( << "No input!" );
86 unsigned long numPts = in->GetNumberOfPoints( );
89 vtkDebugMacro( << "No points!" );
94 // Update input, if needed
95 this->InvokeEvent( vtkCommand::StartEvent, NULL );
98 this->InvokeEvent( vtkCommand::EndEvent, NULL );
100 // Update some visualization objects
101 if( !this->LookupTable )
102 this->CreateDefaultLookupTable( );
103 aren->GetRenderWindow( )->MakeCurrent( );
105 // Check clipping planes
106 int numClipPlanes = this->GetNumberOfClippingPlanes( );
107 if( numClipPlanes > 6 )
109 vtkErrorMacro( << "OpenGL has a limit of 6 clipping planes" );
114 // Add all the clipping planes
117 for( int i = 0; i < numClipPlanes; i++ )
119 this->GetClippingPlaneInDataCoords( act->GetMatrix( ), i, eq );
121 clipPlaneId = static_cast< GLenum >( GL_CLIP_PLANE0 + i );
122 glEnable( clipPlaneId );
123 glClipPlane( clipPlaneId, eq );
128 this->MapScalars( act->GetProperty( )->GetOpacity( ) );
130 // Configure textures
131 if( this->ColorTextureMap )
134 if( !this->InternalColorTexture )
136 this->InternalColorTexture =
137 vtkSmartPointer< vtkOpenGLTexture >::New( );
138 this->InternalColorTexture->RepeatOff( );
141 this->InternalColorTexture->SetInputData( this->ColorTextureMap );
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 );
151 bool renderNeeded = !this->ImmediateModeRendering;
152 renderNeeded &= !this->GetGlobalImmediateModeRendering( );
154 // Something has changed in the pipeline?
156 this->GetMTime( ) > this->BuildTime ||
157 in->GetMTime( ) > this->BuildTime ||
158 act->GetProperty( )->GetMTime( ) > this->BuildTime ||
159 aren->GetRenderWindow( ) != this->LastWindow
162 // Update visualization objects
163 this->ReleaseGraphicsResources( aren->GetRenderWindow( ) );
164 this->LastWindow = aren->GetRenderWindow( );
170 if( this->ColorTextureMap )
171 this->InternalColorTexture->Load( aren );
174 // Time the actual drawing
175 this->Timer->StartTimer( );
176 noAbort = this->Draw( aren, act );
177 this->Timer->StopTimer( );
182 this->BuildTime.Modified( );
186 // If nothing changed, just draw the mapped mesh
191 if( this->ColorTextureMap )
192 this->InternalColorTexture->Load( aren );
195 // Time the actual drawing
196 this->Timer->StartTimer( );
197 this->Draw( aren, act );
198 this->Timer->StopTimer( );
204 // if we are in immediate mode rendering we always
205 // want to draw the primitives here
210 if( this->ColorTextureMap )
211 this->InternalColorTexture->Load( aren );
214 // Time the actual drawing
215 this->Timer->StartTimer( );
216 this->Draw( aren, act );
217 this->Timer->StopTimer( );
220 this->TimeToDraw = this->Timer->GetElapsedTime( );
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 );
227 for( int c = 0; c < numClipPlanes; c++ )
229 GLenum clipPlaneId = static_cast< GLenum >( GL_CLIP_PLANE0 + c );
230 glDisable( clipPlaneId );
233 vtkOpenGLCheckErrorMacro( "failed after RenderPiece\n" );
236 // -------------------------------------------------------------------------
238 void cpPlugins::Extensions::Visualization::OpenGLMeshMapper< M >::
239 ReleaseGraphicsResources( vtkWindow* win )
241 if( win && win->GetMapped( ) )
244 vtkOpenGLCheckErrorMacro( "failed after ReleaseGraphicsResources" );
247 this->LastWindow = NULL;
249 // TAKEN FROM BASIC vtkOpenGLPolyDataMapper:
250 // We may not want to do this here.
252 if( this->InternalColorTexture )
253 this->InternalColorTexture->ReleaseGraphicsResources( win );
257 // -------------------------------------------------------------------------
259 int cpPlugins::Extensions::Visualization::OpenGLMeshMapper< M >::
260 Draw( vtkRenderer* aren, vtkActor* act )
262 vtkOpenGLClearErrorMacro( );
264 // First and second initialization check
265 if( this->FirstRendering )
266 this->FirstRendering = !( this->_ConfigureOpenGL( ) );
267 if( this->FirstRendering )
270 vtkOpenGLRenderer* ren = static_cast< vtkOpenGLRenderer* >( aren );
271 int rep, interpolation;
274 vtkUnsignedCharArray* c = NULL;
277 M* input = this->GetInput( );
279 vtkIdType cellNum = 0;
281 int resolve = 0, zResolve = 0;
285 prop = act->GetProperty( );
287 // get the transparency
288 tran = prop->GetOpacity( );
290 // if the primitives are invisable then get out of here
294 // get the representation ( e.g., surface / wireframe / points )
295 rep = prop->GetRepresentation( );
297 // get the shading interpolation
298 interpolation = prop->GetInterpolation( );
300 // are they cell or point scalars
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( )
311 this->ScalarMode != VTK_SCALAR_MODE_USE_POINT_FIELD_DATA
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 );
326 if( this->ScalarMaterialMode == VTK_MATERIALMODE_DEFAULT )
328 if( prop->GetAmbient( ) > prop->GetDiffuse( ) )
329 lmcolorMode = GL_AMBIENT;
331 lmcolorMode = GL_DIFFUSE;
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 );
344 unsigned long idx = 0;
347 idx |= CPPLUGINS_VTK_PDM_COLORS;
349 idx |= CPPLUGINS_VTK_PDM_OPAQUE_COLORS;
352 idx |= CPPLUGINS_VTK_PDM_CELL_COLORS;
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;
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;
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;
369 if( this->GetResolveCoincidentTopology( ) )
372 if( this->GetResolveCoincidentTopology( ) == VTK_RESOLVE_SHIFT_ZBUFFER )
375 zRes = this->GetResolveCoincidentTopologyZShift( );
379 #ifdef GL_VERSION_1_1
381 glEnable( GL_POLYGON_OFFSET_FILL );
382 this->GetResolveCoincidentTopologyPolygonOffsetParameters( f, u );
383 glPolygonOffset( f, u );
389 // we need to know the total number of cells so that we can
391 this->TotalCells = input->GetNumberOfCells( );
394 if( this->VBOSupported )
396 glBindBuffer( GL_ARRAY_BUFFER, GLuint( this->VBOID1 ) );
398 void* ptr = glMapBuffer( GL_ARRAY_BUFFER, GL_READ_WRITE );
401 // Copy source points to OpenGL buffer
403 input->GetPoints( )->CastToSTLContainer( ).data( );
404 TPoint* dest = reinterpret_cast< TPoint* >( ptr );
406 std::copy( src, src + input->GetNumberOfPoints( ), dest );
407 glUnmapBuffer( GL_ARRAY_BUFFER );
411 std::size_t pSize = input->GetNumberOfPoints( ) * sizeof( TPoint );
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 ) );
418 // Prepare to render polygons
419 glEnableClientState( GL_NORMAL_ARRAY );
420 glEnableClientState( GL_VERTEX_ARRAY );
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++ )
428 const TCell* cell = cIt.Value( );
429 unsigned int nPoints = this->Sizes[ nCell ];
431 // Infere rendering mode
433 switch( prop->GetRepresentation( ) )
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;
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,
452 case VTK_WIREFRAME: mode = GL_LINE_LOOP; break;
453 case VTK_POINTS: default: mode = GL_POINTS; break;
456 // Actual draw all elements
458 glDisable( GL_LIGHTING );
460 if( nPoints == 2 && zResolve )
461 glDepthRange( zRes, 1. );
464 mode, nPoints, this->IndexElementType, ( GLuint* )( 0 ) + accum
469 glEnable( GL_LIGHTING );
473 glDisableClientState( GL_VERTEX_ARRAY );
474 glDisableClientState( GL_NORMAL_ARRAY );
476 glBindBuffer( GL_ARRAY_BUFFER, 0 );
477 glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
481 std::cout << "Not VBO rendering!!!" << std::endl;
488 glDepthRange( 0., 1. );
491 #ifdef GL_VERSION_1_1
492 glDisable( GL_POLYGON_OFFSET_FILL );
497 vtkOpenGLCheckErrorMacro( "failed after Draw" );
498 this->UpdateProgress( 1.0 );
502 // -------------------------------------------------------------------------
504 cpPlugins::Extensions::Visualization::OpenGLMeshMapper< M >::
508 FirstRendering( true ),
512 // Infere index element type
513 switch( sizeof( TIndex ) )
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;
521 // Infere point value type
522 if( typeid( TScalar ) == typeid( float ) )
523 this->ElementValueType = GL_FLOAT;
525 this->ElementValueType = GL_DOUBLE;
528 // -------------------------------------------------------------------------
530 cpPlugins::Extensions::Visualization::OpenGLMeshMapper< M >::
533 if( this->LastWindow )
534 this->ReleaseGraphicsResources( this->LastWindow );
535 if( this->VBOSupported )
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;
546 // -------------------------------------------------------------------------
548 bool cpPlugins::Extensions::Visualization::OpenGLMeshMapper< M >::
551 M* input = this->GetInput( );
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" ) );
575 // Check once again VBO extension
577 glGenBuffers != NULL &&
578 glBindBuffer != NULL &&
579 glBufferData != NULL &&
580 glBufferSubData != NULL &&
581 glMapBuffer != NULL &&
582 glUnmapBuffer != NULL &&
583 glDeleteBuffers != NULL &&
584 glGetBufferParameteriv != NULL
586 this->VBOSupported = true;
588 this->VBOSupported = false;
590 // Check if VBO ( Vertex Buffer Object ) is supported
591 std::string str = ( const char* )( glGetString( GL_EXTENSIONS ) );
593 ( str.find( "GL_ARB_vertex_buffer_object" ) != std::string::npos );
596 if( this->VBOSupported )
598 // Create points and normals buffers
600 std::size_t pSize = input->GetNumberOfPoints( ) * sizeof( TPoint );
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 );
613 // Create indices buffer
614 const TCellsContainer* cells = input->GetCells( );
618 << "This QuadEdgeMesh does not have any cells!"
624 unsigned int cellPointsCount = 0;
625 this->Sizes.clear( );
626 for( cIt = cells->Begin( ); cIt != cells->End( ); cIt++ )
628 this->Sizes.push_back( cIt.Value( )->GetNumberOfPoints( ) );
629 cellPointsCount += this->Sizes.back( );
632 this->Indices.resize( cellPointsCount );
633 unsigned int indId = 0;
634 for( cIt = cells->Begin( ); cIt != cells->End( ); cIt++ )
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( );
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( );
651 glGenBuffers( 1, &id2 );
652 glBindBuffer( GL_ARRAY_BUFFER, id2 );
653 glBufferData( GL_ARRAY_BUFFER, iSize, indices, GL_STATIC_DRAW );
656 glGetBufferParameteriv( GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &bSize );
659 glDeleteBuffers( 1, &id2 );
661 vtkErrorMacro( << "Data size mismatch with input array" );
664 this->VBOID2 = ( unsigned int )( id2 );
670 #endif // __CPPLUGINS__EXTENSIONS__VISUALIZATION__OPENGLMESHMAPPER__HXX__