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
20 // some definitions for what the polydata has in it
21 #define CPPLUGINS_VTK_PDM_NORMALS 0x0001
22 #define CPPLUGINS_VTK_PDM_COLORS 0x0002
23 #define CPPLUGINS_VTK_PDM_TCOORDS 0x0004
24 #define CPPLUGINS_VTK_PDM_CELL_COLORS 0x0008
25 #define CPPLUGINS_VTK_PDM_CELL_NORMALS 0x0010
26 #define CPPLUGINS_VTK_PDM_POINT_TYPE_FLOAT 0x0020
27 #define CPPLUGINS_VTK_PDM_POINT_TYPE_DOUBLE 0x0040
28 #define CPPLUGINS_VTK_PDM_NORMAL_TYPE_FLOAT 0x0080
29 #define CPPLUGINS_VTK_PDM_NORMAL_TYPE_DOUBLE 0x0100
30 #define CPPLUGINS_VTK_PDM_TCOORD_TYPE_FLOAT 0x0200
31 #define CPPLUGINS_VTK_PDM_TCOORD_TYPE_DOUBLE 0x0400
32 #define CPPLUGINS_VTK_PDM_TCOORD_1D 0x0800
33 #define CPPLUGINS_VTK_PDM_OPAQUE_COLORS 0x1000
34 #define CPPLUGINS_VTK_PDM_USE_FIELD_DATA 0x2000
36 // -------------------------------------------------------------------------
38 typename cpPlugins::Extensions::Visualization::OpenGLMeshMapper< M >::
39 Self* cpPlugins::Extensions::Visualization::OpenGLMeshMapper< M >::
42 return( new Self( ) );
45 // -------------------------------------------------------------------------
47 void cpPlugins::Extensions::Visualization::OpenGLMeshMapper< M >::
48 RenderPiece( vtkRenderer* aren, vtkActor* act )
50 vtkOpenGLClearErrorMacro( );
52 // Is the renderer correctly initialized?
53 if( aren->GetRenderWindow( )->CheckAbortStatus( ) )
56 // Get input mesh ( and check it )
57 M* in = this->GetInput( );
60 vtkErrorMacro( << "No input!" );
64 unsigned long numPts = in->GetNumberOfPoints( );
67 vtkDebugMacro( << "No points!" );
72 // Update input, if needed
73 this->InvokeEvent( vtkCommand::StartEvent, NULL );
76 this->InvokeEvent( vtkCommand::EndEvent, NULL );
78 // Update some visualization objects
79 if( !this->LookupTable )
80 this->CreateDefaultLookupTable( );
81 aren->GetRenderWindow( )->MakeCurrent( );
83 // Check clipping planes
84 int numClipPlanes = this->GetNumberOfClippingPlanes( );
85 if( numClipPlanes > 6 )
87 vtkErrorMacro( << "OpenGL has a limit of 6 clipping planes" );
92 // Add all the clipping planes
95 for( int i = 0; i < numClipPlanes; i++ )
97 this->GetClippingPlaneInDataCoords( act->GetMatrix( ), i, eq );
99 clipPlaneId = static_cast< GLenum >( GL_CLIP_PLANE0 + i );
100 glEnable( clipPlaneId );
101 glClipPlane( clipPlaneId, eq );
106 this->MapScalars( act->GetProperty( )->GetOpacity( ) );
108 // Configure textures
109 if( this->ColorTextureMap )
112 if( !this->InternalColorTexture )
114 this->InternalColorTexture =
115 vtkSmartPointer< vtkOpenGLTexture >::New( );
116 this->InternalColorTexture->RepeatOff( );
119 this->InternalColorTexture->SetInputData( this->ColorTextureMap );
122 // Keep color from interacting with texture.
123 float info[ 4 ] = { float( 1 ), float( 1 ), float( 1 ), float( 1 ) };
124 glMaterialfv( GL_FRONT_AND_BACK, GL_DIFFUSE, info );
129 bool renderNeeded = !this->ImmediateModeRendering;
130 renderNeeded &= !this->GetGlobalImmediateModeRendering( );
132 // Something has changed in the pipeline?
134 this->GetMTime( ) > this->BuildTime ||
135 in->GetMTime( ) > this->BuildTime ||
136 act->GetProperty( )->GetMTime( ) > this->BuildTime ||
137 aren->GetRenderWindow( ) != this->LastWindow
140 // Update visualization objects
141 this->ReleaseGraphicsResources( aren->GetRenderWindow( ) );
142 this->LastWindow = aren->GetRenderWindow( );
148 if( this->ColorTextureMap )
149 this->InternalColorTexture->Load( aren );
152 // Time the actual drawing
153 this->Timer->StartTimer( );
154 noAbort = this->Draw( aren, act );
155 this->Timer->StopTimer( );
160 this->BuildTime.Modified( );
164 // If nothing changed, just draw the mapped mesh
169 if( this->ColorTextureMap )
170 this->InternalColorTexture->Load( aren );
173 // Time the actual drawing
174 this->Timer->StartTimer( );
175 this->Draw( aren, act );
176 this->Timer->StopTimer( );
182 // if we are in immediate mode rendering we always
183 // want to draw the primitives here
188 if( this->ColorTextureMap )
189 this->InternalColorTexture->Load( aren );
192 // Time the actual drawing
193 this->Timer->StartTimer( );
194 this->Draw( aren, act );
195 this->Timer->StopTimer( );
198 this->TimeToDraw = this->Timer->GetElapsedTime( );
200 // If the timer is not accurate enough, set it to a small
201 // time so that it is not zero
202 if( this->TimeToDraw == double( 0 ) )
203 this->TimeToDraw = double( 1e-3 );
205 for( int c = 0; c < numClipPlanes; c++ )
207 GLenum clipPlaneId = static_cast< GLenum >( GL_CLIP_PLANE0 + c );
208 glDisable( clipPlaneId );
211 vtkOpenGLCheckErrorMacro( "failed after RenderPiece\n" );
214 // -------------------------------------------------------------------------
216 void cpPlugins::Extensions::Visualization::OpenGLMeshMapper< M >::
217 ReleaseGraphicsResources( vtkWindow* win )
219 if( win && win->GetMapped( ) )
222 vtkOpenGLCheckErrorMacro( "failed after ReleaseGraphicsResources" );
225 this->LastWindow = NULL;
227 // TAKEN FROM BASIC vtkOpenGLPolyDataMapper:
228 // We may not want to do this here.
230 if( this->InternalColorTexture )
231 this->InternalColorTexture->ReleaseGraphicsResources( win );
235 // -------------------------------------------------------------------------
237 int cpPlugins::Extensions::Visualization::OpenGLMeshMapper< M >::
238 Draw( vtkRenderer* aren, vtkActor* act )
240 vtkOpenGLClearErrorMacro( );
242 // First and second initialization check
243 if( this->FirstRendering )
244 this->FirstRendering = !( this->_ConfigureOpenGL( ) );
245 if( this->FirstRendering )
248 vtkOpenGLRenderer* ren = static_cast< vtkOpenGLRenderer* >( aren );
249 int rep, interpolation;
252 vtkUnsignedCharArray* c = NULL;
255 M* input = this->GetInput( );
257 vtkIdType cellNum = 0;
259 int resolve = 0, zResolve = 0;
263 prop = act->GetProperty( );
265 // get the transparency
266 tran = prop->GetOpacity( );
268 // if the primitives are invisable then get out of here
272 // get the representation ( e.g., surface / wireframe / points )
273 rep = prop->GetRepresentation( );
275 // get the shading interpolation
276 interpolation = prop->GetInterpolation( );
278 // are they cell or point scalars
284 this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_DATA ||
285 this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_FIELD_DATA ||
286 this->ScalarMode == VTK_SCALAR_MODE_USE_FIELD_DATA ||
287 !input->GetPointData( )
289 this->ScalarMode != VTK_SCALAR_MODE_USE_POINT_FIELD_DATA
297 // if we are doing vertex colors then set lmcolor to adjust
298 // the current materials ambient and diffuse values using
299 // vertex color commands otherwise tell it not to.
300 glDisable( GL_COLOR_MATERIAL );
304 if( this->ScalarMaterialMode == VTK_MATERIALMODE_DEFAULT )
306 if( prop->GetAmbient( ) > prop->GetDiffuse( ) )
307 lmcolorMode = GL_AMBIENT;
309 lmcolorMode = GL_DIFFUSE;
311 else if( this->ScalarMaterialMode == VTK_MATERIALMODE_AMBIENT_AND_DIFFUSE )
312 lmcolorMode = GL_AMBIENT_AND_DIFFUSE;
313 else if( this->ScalarMaterialMode == VTK_MATERIALMODE_AMBIENT )
314 lmcolorMode = GL_AMBIENT;
315 else // if( this->ScalarMaterialMode == VTK_MATERIALMODE_DIFFUSE )
316 lmcolorMode = GL_DIFFUSE;
317 glColorMaterial( GL_FRONT_AND_BACK, lmcolorMode );
318 glEnable( GL_COLOR_MATERIAL );
322 unsigned long idx = 0;
325 idx |= CPPLUGINS_VTK_PDM_COLORS;
327 idx |= CPPLUGINS_VTK_PDM_OPAQUE_COLORS;
330 idx |= CPPLUGINS_VTK_PDM_CELL_COLORS;
332 idx |= CPPLUGINS_VTK_PDM_CELL_NORMALS;
333 if( this->ScalarMode == VTK_SCALAR_MODE_USE_FIELD_DATA )
334 idx |= CPPLUGINS_VTK_PDM_USE_FIELD_DATA;
336 // store the types in the index
337 if( typeid( typename M::CoordRepType ) == typeid( float ) )
338 idx |= CPPLUGINS_VTK_PDM_POINT_TYPE_FLOAT;
339 else if( typeid( typename M::CoordRepType ) == typeid( double ) )
340 idx |= CPPLUGINS_VTK_PDM_POINT_TYPE_DOUBLE;
342 if( typeid( typename M::CoordRepType ) == typeid( float ) )
343 idx |= CPPLUGINS_VTK_PDM_NORMAL_TYPE_FLOAT;
344 else if( typeid( typename M::CoordRepType ) == typeid( double ) )
345 idx |= CPPLUGINS_VTK_PDM_NORMAL_TYPE_DOUBLE;
347 if( this->GetResolveCoincidentTopology( ) )
350 if( this->GetResolveCoincidentTopology( ) == VTK_RESOLVE_SHIFT_ZBUFFER )
353 zRes = this->GetResolveCoincidentTopologyZShift( );
357 #ifdef GL_VERSION_1_1
359 glEnable( GL_POLYGON_OFFSET_FILL );
360 this->GetResolveCoincidentTopologyPolygonOffsetParameters( f, u );
361 glPolygonOffset( f, u );
367 // we need to know the total number of cells so that we can
369 this->TotalCells = input->GetNumberOfCells( );
372 if( this->VBOSupported )
374 glBindBuffer( GL_ARRAY_BUFFER, GLuint( this->VBOID1 ) );
376 void* ptr = glMapBuffer( GL_ARRAY_BUFFER, GL_READ_WRITE );
379 // Copy source points to OpenGL buffer
381 input->GetPoints( )->CastToSTLContainer( ).data( );
382 TPoint* dest = reinterpret_cast< TPoint* >( ptr );
384 std::copy( src, src + input->GetNumberOfPoints( ), dest );
385 glUnmapBuffer( GL_ARRAY_BUFFER );
389 std::size_t pSize = input->GetNumberOfPoints( ) * sizeof( TPoint );
391 // Bind vertices, normals and indices
392 glNormalPointer( this->ElementValueType, 0, ( void* )( pSize ) );
393 glVertexPointer( 3, this->ElementValueType, 0, 0 );
394 glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, GLuint( this->VBOID2 ) );
396 // Prepare to render polygons
397 glEnableClientState( GL_NORMAL_ARRAY );
398 glEnableClientState( GL_VERTEX_ARRAY );
400 // Iterate over all input cells
401 unsigned int accum = 0;
402 const TCellsContainer* cells = input->GetCells( );
403 TCellIt cIt = cells->Begin( );
404 for( unsigned int nCell = 0; cIt != cells->End( ); nCell++, cIt++ )
406 const TCell* cell = cIt.Value( );
407 unsigned int nPoints = this->Sizes[ nCell ];
409 // Infere rendering mode
411 switch( prop->GetRepresentation( ) )
417 case 1: mode = GL_POINTS; break;
418 case 2: mode = GL_LINES; break;
419 case 3: mode = GL_TRIANGLES; break;
420 case 4: mode = GL_QUADS; break;
421 default: mode = GL_POLYGON; break;
423 // TODO: GL_LINE_STRIP,
424 // TODO: GL_LINE_LOOP,
425 // TODO: GL_TRIANGLE_STRIP,
426 // TODO: GL_TRIANGLE_FAN,
427 // TODO: GL_QUAD_STRIP,
430 case VTK_WIREFRAME: mode = GL_LINE_LOOP; break;
431 case VTK_POINTS: default: mode = GL_POINTS; break;
434 // Actual draw all elements
436 glDisable( GL_LIGHTING );
438 if( nPoints == 2 && zResolve )
439 glDepthRange( zRes, 1. );
442 mode, nPoints, this->IndexElementType, ( GLuint* )( 0 ) + accum
447 glEnable( GL_LIGHTING );
451 glDisableClientState( GL_VERTEX_ARRAY );
452 glDisableClientState( GL_NORMAL_ARRAY );
454 glBindBuffer( GL_ARRAY_BUFFER, 0 );
455 glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
459 std::cout << "Not VBO rendering!!!" << std::endl;
466 glDepthRange( 0., 1. );
469 #ifdef GL_VERSION_1_1
470 glDisable( GL_POLYGON_OFFSET_FILL );
475 vtkOpenGLCheckErrorMacro( "failed after Draw" );
476 this->UpdateProgress( 1.0 );
480 // -------------------------------------------------------------------------
482 cpPlugins::Extensions::Visualization::OpenGLMeshMapper< M >::
486 FirstRendering( true ),
490 // Infere index element type
491 switch( sizeof( TIndex ) )
493 case 1 : this->IndexElementType = GL_UNSIGNED_BYTE; break;
494 case 2 : this->IndexElementType = GL_UNSIGNED_SHORT; break;
495 case 4 : this->IndexElementType = GL_UNSIGNED_INT; break;
496 default: this->IndexElementType = GL_UNSIGNED_BYTE; break;
499 // Infere point value type
500 if( typeid( TScalar ) == typeid( float ) )
501 this->ElementValueType = GL_FLOAT;
503 this->ElementValueType = GL_DOUBLE;
506 // -------------------------------------------------------------------------
508 cpPlugins::Extensions::Visualization::OpenGLMeshMapper< M >::
511 if( this->LastWindow )
512 this->ReleaseGraphicsResources( this->LastWindow );
513 if( this->VBOSupported )
515 GLuint id1 = GLuint( this->VBOID1 );
516 GLuint id2 = GLuint( this->VBOID2 );
517 if( id1 != GLuint( 0 ) ) glDeleteBuffers( 1, &id1 );
518 if( id2 != GLuint( 0 ) ) glDeleteBuffers( 1, &id2 );
519 this->VBOID1 = this->VBOID2 = 0;
524 // -------------------------------------------------------------------------
526 bool cpPlugins::Extensions::Visualization::OpenGLMeshMapper< M >::
529 M* input = this->GetInput( );
533 // Check if VBO ( Vertex Buffer Object ) is supported
534 std::string str = ( const char* )( glGetString( GL_EXTENSIONS ) );
536 ( str.find( "GL_ARB_vertex_buffer_object" ) != std::string::npos );
538 if( this->VBOSupported )
540 // Create points and normals buffers
542 std::size_t pSize = input->GetNumberOfPoints( ) * sizeof( TPoint );
544 input->GetPointNormalsContainer( ).size( ) * sizeof( TVector );
545 const TPoint* verts =
546 input->GetPoints( )->CastToSTLContainer( ).data( );
547 const TVector* norms = input->GetPointNormalsContainer( ).data( );
548 glGenBuffers( 1, &id1 );
549 glBindBuffer( GL_ARRAY_BUFFER, id1 );
550 glBufferData( GL_ARRAY_BUFFER, pSize + nSize, 0, GL_STREAM_DRAW );
551 glBufferSubData( GL_ARRAY_BUFFER, 0, pSize, verts );
552 glBufferSubData( GL_ARRAY_BUFFER, pSize, nSize, norms );
553 this->VBOID1 = ( unsigned int )( id1 );
555 // Create indices buffer
556 const TCellsContainer* cells = input->GetCells( );
560 << "This QuadEdgeMesh does not have any cells!"
566 unsigned int cellPointsCount = 0;
567 this->Sizes.clear( );
568 for( cIt = cells->Begin( ); cIt != cells->End( ); cIt++ )
570 this->Sizes.push_back( cIt.Value( )->GetNumberOfPoints( ) );
571 cellPointsCount += this->Sizes.back( );
574 this->Indices.resize( cellPointsCount );
575 unsigned int indId = 0;
576 for( cIt = cells->Begin( ); cIt != cells->End( ); cIt++ )
578 const typename M::TQuadEdgeCell* cell =
579 dynamic_cast< const typename M::TQuadEdgeCell* >( cIt.Value( ) );
580 const typename M::TPrimalEdge* edge =
581 cell->GetEntryPrimalEdge( );
582 typename M::TPrimalEdge::ConstIterator iIt = edge->BeginLnext( );
583 for( ; iIt != edge->EndLnext( ); ++iIt )
584 this->Indices[ indId++ ] = ( *iIt )->GetOrigin( );
588 // Attach index buffer to VBO
589 std::size_t iSize = std::size_t( this->Indices.size( ) );
590 iSize *= sizeof( TIndex );
591 const unsigned int* indices = this->Indices.data( );
593 glGenBuffers( 1, &id2 );
594 glBindBuffer( GL_ARRAY_BUFFER, id2 );
595 glBufferData( GL_ARRAY_BUFFER, iSize, indices, GL_STATIC_DRAW );
598 glGetBufferParameteriv( GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &bSize );
601 glDeleteBuffers( 1, &id2 );
603 vtkErrorMacro( << "Data size mismatch with input array" );
606 this->VBOID2 = ( unsigned int )( id2 );
612 #endif // __CPPLUGINS__EXTENSIONS__VISUALIZATION__OPENGLMESHMAPPER__HXX__