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
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
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
69 // -------------------------------------------------------------------------
71 typename cpPlugins::Extensions::Visualization::OpenGLMeshMapper< M >::
72 Self* cpPlugins::Extensions::Visualization::OpenGLMeshMapper< M >::
75 return( new Self( ) );
78 // -------------------------------------------------------------------------
80 void cpPlugins::Extensions::Visualization::OpenGLMeshMapper< M >::
81 RenderPiece( vtkRenderer* aren, vtkActor* act )
83 vtkOpenGLClearErrorMacro( );
85 // Is the renderer correctly initialized?
86 if( aren->GetRenderWindow( )->CheckAbortStatus( ) )
89 // Get input mesh ( and check it )
90 M* in = this->GetInput( );
93 vtkErrorMacro( << "No input!" );
97 unsigned long numPts = in->GetNumberOfPoints( );
100 vtkDebugMacro( << "No points!" );
105 // Update input, if needed
106 this->InvokeEvent( vtkCommand::StartEvent, NULL );
109 this->InvokeEvent( vtkCommand::EndEvent, NULL );
111 // Update some visualization objects
112 if( !this->LookupTable )
113 this->CreateDefaultLookupTable( );
114 aren->GetRenderWindow( )->MakeCurrent( );
116 // Check clipping planes
117 int numClipPlanes = this->GetNumberOfClippingPlanes( );
118 if( numClipPlanes > 6 )
120 vtkErrorMacro( << "OpenGL has a limit of 6 clipping planes" );
125 // Add all the clipping planes
128 for( int i = 0; i < numClipPlanes; i++ )
130 this->GetClippingPlaneInDataCoords( act->GetMatrix( ), i, eq );
132 clipPlaneId = static_cast< GLenum >( GL_CLIP_PLANE0 + i );
133 glEnable( clipPlaneId );
134 glClipPlane( clipPlaneId, eq );
139 this->MapScalars( act->GetProperty( )->GetOpacity( ) );
141 // Configure textures
142 if( this->ColorTextureMap )
145 if( !this->InternalColorTexture )
147 this->InternalColorTexture =
148 vtkSmartPointer< vtkOpenGLTexture >::New( );
149 this->InternalColorTexture->RepeatOff( );
152 this->InternalColorTexture->SetInputData( this->ColorTextureMap );
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 );
162 bool renderNeeded = !this->ImmediateModeRendering;
163 renderNeeded &= !this->GetGlobalImmediateModeRendering( );
165 // Something has changed in the pipeline?
167 this->GetMTime( ) > this->BuildTime ||
168 in->GetMTime( ) > this->BuildTime ||
169 act->GetProperty( )->GetMTime( ) > this->BuildTime ||
170 aren->GetRenderWindow( ) != this->LastWindow
173 // Update visualization objects
174 this->ReleaseGraphicsResources( aren->GetRenderWindow( ) );
175 this->LastWindow = aren->GetRenderWindow( );
181 if( this->ColorTextureMap )
182 this->InternalColorTexture->Load( aren );
185 // Time the actual drawing
186 this->Timer->StartTimer( );
187 noAbort = this->Draw( aren, act );
188 this->Timer->StopTimer( );
193 this->BuildTime.Modified( );
197 // If nothing changed, just draw the mapped mesh
202 if( this->ColorTextureMap )
203 this->InternalColorTexture->Load( aren );
206 // Time the actual drawing
207 this->Timer->StartTimer( );
208 this->Draw( aren, act );
209 this->Timer->StopTimer( );
215 // if we are in immediate mode rendering we always
216 // want to draw the primitives here
221 if( this->ColorTextureMap )
222 this->InternalColorTexture->Load( aren );
225 // Time the actual drawing
226 this->Timer->StartTimer( );
227 this->Draw( aren, act );
228 this->Timer->StopTimer( );
231 this->TimeToDraw = this->Timer->GetElapsedTime( );
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 );
238 for( int c = 0; c < numClipPlanes; c++ )
240 GLenum clipPlaneId = static_cast< GLenum >( GL_CLIP_PLANE0 + c );
241 glDisable( clipPlaneId );
244 vtkOpenGLCheckErrorMacro( "failed after RenderPiece\n" );
247 // -------------------------------------------------------------------------
249 void cpPlugins::Extensions::Visualization::OpenGLMeshMapper< M >::
250 ReleaseGraphicsResources( vtkWindow* win )
252 if( win && win->GetMapped( ) )
255 vtkOpenGLCheckErrorMacro( "failed after ReleaseGraphicsResources" );
258 this->LastWindow = NULL;
260 // TAKEN FROM BASIC vtkOpenGLPolyDataMapper:
261 // We may not want to do this here.
263 if( this->InternalColorTexture )
264 this->InternalColorTexture->ReleaseGraphicsResources( win );
268 // -------------------------------------------------------------------------
270 int cpPlugins::Extensions::Visualization::OpenGLMeshMapper< M >::
271 Draw( vtkRenderer* aren, vtkActor* act )
273 vtkOpenGLClearErrorMacro( );
275 // First and second initialization check
276 if( this->FirstRendering )
277 this->FirstRendering = !( this->_ConfigureOpenGL( ) );
278 if( this->FirstRendering )
281 vtkOpenGLRenderer* ren = static_cast< vtkOpenGLRenderer* >( aren );
282 int rep, interpolation;
285 vtkUnsignedCharArray* c = NULL;
288 M* input = this->GetInput( );
290 vtkIdType cellNum = 0;
292 int resolve = 0, zResolve = 0;
296 prop = act->GetProperty( );
298 // get the transparency
299 tran = prop->GetOpacity( );
301 // if the primitives are invisable then get out of here
305 // get the representation ( e.g., surface / wireframe / points )
306 rep = prop->GetRepresentation( );
308 // get the shading interpolation
309 interpolation = prop->GetInterpolation( );
311 // are they cell or point scalars
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( )
322 this->ScalarMode != VTK_SCALAR_MODE_USE_POINT_FIELD_DATA
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 );
337 if( this->ScalarMaterialMode == VTK_MATERIALMODE_DEFAULT )
339 if( prop->GetAmbient( ) > prop->GetDiffuse( ) )
340 lmcolorMode = GL_AMBIENT;
342 lmcolorMode = GL_DIFFUSE;
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 );
355 unsigned long idx = 0;
358 idx |= CPPLUGINS_VTK_PDM_COLORS;
360 idx |= CPPLUGINS_VTK_PDM_OPAQUE_COLORS;
363 idx |= CPPLUGINS_VTK_PDM_CELL_COLORS;
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;
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;
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;
380 if( this->GetResolveCoincidentTopology( ) )
383 if( this->GetResolveCoincidentTopology( ) == VTK_RESOLVE_SHIFT_ZBUFFER )
386 zRes = this->GetResolveCoincidentTopologyZShift( );
390 #ifdef GL_VERSION_1_1
392 glEnable( GL_POLYGON_OFFSET_FILL );
393 this->GetResolveCoincidentTopologyPolygonOffsetParameters( f, u );
394 glPolygonOffset( f, u );
400 // we need to know the total number of cells so that we can
402 this->TotalCells = input->GetNumberOfCells( );
405 if( this->VBOSupported )
407 glBindBuffer( GL_ARRAY_BUFFER, GLuint( this->VBOID1 ) );
409 void* ptr = glMapBuffer( GL_ARRAY_BUFFER, GL_READ_WRITE );
412 // Copy source points to OpenGL buffer
414 input->GetPoints( )->CastToSTLContainer( ).data( );
415 TPoint* dest = reinterpret_cast< TPoint* >( ptr );
417 std::copy( src, src + input->GetNumberOfPoints( ), dest );
418 glUnmapBuffer( GL_ARRAY_BUFFER );
422 std::size_t pSize = input->GetNumberOfPoints( ) * sizeof( TPoint );
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 ) );
429 // Prepare to render polygons
430 glEnableClientState( GL_NORMAL_ARRAY );
431 glEnableClientState( GL_VERTEX_ARRAY );
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++ )
439 const TCell* cell = cIt.Value( );
440 unsigned int nPoints = this->Sizes[ nCell ];
442 // Infere rendering mode
444 switch( prop->GetRepresentation( ) )
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;
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,
463 case VTK_WIREFRAME: mode = GL_LINE_LOOP; break;
464 case VTK_POINTS: default: mode = GL_POINTS; break;
467 // Actual draw all elements
469 glDisable( GL_LIGHTING );
471 if( nPoints == 2 && zResolve )
472 glDepthRange( zRes, 1. );
475 mode, nPoints, this->IndexElementType, ( GLuint* )( 0 ) + accum
480 glEnable( GL_LIGHTING );
484 glDisableClientState( GL_VERTEX_ARRAY );
485 glDisableClientState( GL_NORMAL_ARRAY );
487 glBindBuffer( GL_ARRAY_BUFFER, 0 );
488 glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
492 std::cout << "Not VBO rendering!!!" << std::endl;
499 glDepthRange( 0., 1. );
502 #ifdef GL_VERSION_1_1
503 glDisable( GL_POLYGON_OFFSET_FILL );
508 vtkOpenGLCheckErrorMacro( "failed after Draw" );
509 this->UpdateProgress( 1.0 );
513 // -------------------------------------------------------------------------
515 cpPlugins::Extensions::Visualization::OpenGLMeshMapper< M >::
519 FirstRendering( true ),
523 // Infere index element type
524 switch( sizeof( TIndex ) )
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;
532 // Infere point value type
533 if( typeid( TScalar ) == typeid( float ) )
534 this->ElementValueType = GL_FLOAT;
536 this->ElementValueType = GL_DOUBLE;
539 // -------------------------------------------------------------------------
541 cpPlugins::Extensions::Visualization::OpenGLMeshMapper< M >::
544 if( this->LastWindow )
545 this->ReleaseGraphicsResources( this->LastWindow );
546 if( this->VBOSupported )
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;
557 // -------------------------------------------------------------------------
559 bool cpPlugins::Extensions::Visualization::OpenGLMeshMapper< M >::
562 M* input = this->GetInput( );
566 // Check if VBO ( Vertex Buffer Object ) is supported
567 std::string str = ( const char* )( glGetString( GL_EXTENSIONS ) );
569 ( str.find( "GL_ARB_vertex_buffer_object" ) != std::string::npos );
571 if( this->VBOSupported )
573 // Create points and normals buffers
575 std::size_t pSize = input->GetNumberOfPoints( ) * sizeof( TPoint );
577 input->GetPointNormalsContainer( ).size( ) * sizeof( TVector );
578 const TPoint* verts =
579 input->GetPoints( )->CastToSTLContainer( ).data( );
580 const TVector* norms = input->GetPointNormalsContainer( ).data( );
581 glGenBuffers( 1, &id1 );
582 glBindBuffer( GL_ARRAY_BUFFER, id1 );
583 glBufferData( GL_ARRAY_BUFFER, pSize + nSize, 0, GL_STREAM_DRAW );
584 glBufferSubData( GL_ARRAY_BUFFER, 0, pSize, verts );
585 glBufferSubData( GL_ARRAY_BUFFER, pSize, nSize, norms );
586 this->VBOID1 = ( unsigned int )( id1 );
588 // Create indices buffer
589 const TCellsContainer* cells = input->GetCells( );
593 << "This QuadEdgeMesh does not have any cells!"
599 unsigned int cellPointsCount = 0;
600 this->Sizes.clear( );
601 for( cIt = cells->Begin( ); cIt != cells->End( ); cIt++ )
603 this->Sizes.push_back( cIt.Value( )->GetNumberOfPoints( ) );
604 cellPointsCount += this->Sizes.back( );
607 this->Indices.resize( cellPointsCount );
608 unsigned int indId = 0;
609 for( cIt = cells->Begin( ); cIt != cells->End( ); cIt++ )
611 const typename M::TQuadEdgeCell* cell =
612 dynamic_cast< const typename M::TQuadEdgeCell* >( cIt.Value( ) );
613 const typename M::TPrimalEdge* edge =
614 cell->GetEntryPrimalEdge( );
615 typename M::TPrimalEdge::ConstIterator iIt = edge->BeginLnext( );
616 for( ; iIt != edge->EndLnext( ); ++iIt )
617 this->Indices[ indId++ ] = ( *iIt )->GetOrigin( );
621 // Attach index buffer to VBO
622 std::size_t iSize = std::size_t( this->Indices.size( ) );
623 iSize *= sizeof( TIndex );
624 const unsigned int* indices = this->Indices.data( );
626 glGenBuffers( 1, &id2 );
627 glBindBuffer( GL_ARRAY_BUFFER, id2 );
628 glBufferData( GL_ARRAY_BUFFER, iSize, indices, GL_STATIC_DRAW );
631 glGetBufferParameteriv( GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &bSize );
634 glDeleteBuffers( 1, &id2 );
636 vtkErrorMacro( << "Data size mismatch with input array" );
639 this->VBOID2 = ( unsigned int )( id2 );
645 #endif // __CPPLUGINS__EXTENSIONS__VISUALIZATION__OPENGLMESHMAPPER__HXX__