1 #include <cpm/VTK/OpenGLMeshMapper.h>
6 #include <vtkCommand.h>
7 #include <vtkImageData.h>
8 #include <vtkOpenGLRenderer.h>
9 #include <vtkProperty.h>
10 #include <vtkTimerLog.h>
11 #include <vtkUnsignedCharArray.h>
13 #include <vtkOpenGL.h>
14 #include <vtkOpenGLError.h>
15 #define GL_GLEXT_PROTOTYPES
18 // some definitions for what the polydata has in it
19 #define CPM_VTK_PDM_NORMALS 0x0001
20 #define CPM_VTK_PDM_COLORS 0x0002
21 #define CPM_VTK_PDM_TCOORDS 0x0004
22 #define CPM_VTK_PDM_CELL_COLORS 0x0008
23 #define CPM_VTK_PDM_CELL_NORMALS 0x0010
24 #define CPM_VTK_PDM_POINT_TYPE_FLOAT 0x0020
25 #define CPM_VTK_PDM_POINT_TYPE_DOUBLE 0x0040
26 #define CPM_VTK_PDM_NORMAL_TYPE_FLOAT 0x0080
27 #define CPM_VTK_PDM_NORMAL_TYPE_DOUBLE 0x0100
28 #define CPM_VTK_PDM_TCOORD_TYPE_FLOAT 0x0200
29 #define CPM_VTK_PDM_TCOORD_TYPE_DOUBLE 0x0400
30 #define CPM_VTK_PDM_TCOORD_1D 0x0800
31 #define CPM_VTK_PDM_OPAQUE_COLORS 0x1000
32 #define CPM_VTK_PDM_USE_FIELD_DATA 0x2000
34 // -------------------------------------------------------------------------
36 typename cpm::VTK::OpenGLMeshMapper< M >::
37 Self* cpm::VTK::OpenGLMeshMapper< M >::
40 return( new Self( ) );
43 // -------------------------------------------------------------------------
45 void cpm::VTK::OpenGLMeshMapper< M >::
46 RenderPiece( vtkRenderer* aren, vtkActor* act )
48 vtkOpenGLClearErrorMacro( );
50 // Is the renderer correctly initialized?
51 if( aren->GetRenderWindow( )->CheckAbortStatus( ) )
54 // Get input mesh ( and check it )
55 M* in = this->GetInput( );
58 vtkErrorMacro( << "No input!" );
62 unsigned long numPts = in->GetNumberOfPoints( );
65 vtkDebugMacro( << "No points!" );
70 // Update input, if needed
71 this->InvokeEvent( vtkCommand::StartEvent, NULL );
74 this->InvokeEvent( vtkCommand::EndEvent, NULL );
76 // Update some visualization objects
77 if( !this->LookupTable )
78 this->CreateDefaultLookupTable( );
79 aren->GetRenderWindow( )->MakeCurrent( );
81 // Check clipping planes
82 int numClipPlanes = this->GetNumberOfClippingPlanes( );
83 if( numClipPlanes > 6 )
85 vtkErrorMacro( << "OpenGL has a limit of 6 clipping planes" );
90 // Add all the clipping planes
93 for( int i = 0; i < numClipPlanes; i++ )
95 this->GetClippingPlaneInDataCoords( act->GetMatrix( ), i, eq );
97 clipPlaneId = static_cast< GLenum >( GL_CLIP_PLANE0 + i );
98 glEnable( clipPlaneId );
99 glClipPlane( clipPlaneId, eq );
104 this->MapScalars( act->GetProperty( )->GetOpacity( ) );
106 // Configure textures
107 if( this->ColorTextureMap )
110 if( !this->InternalColorTexture )
112 this->InternalColorTexture =
113 vtkSmartPointer< vtkOpenGLTexture >::New( );
114 this->InternalColorTexture->RepeatOff( );
117 this->InternalColorTexture->SetInputData( this->ColorTextureMap );
120 // Keep color from interacting with texture.
121 float info[ 4 ] = { float( 1 ), float( 1 ), float( 1 ), float( 1 ) };
122 glMaterialfv( GL_FRONT_AND_BACK, GL_DIFFUSE, info );
127 bool renderNeeded = !this->ImmediateModeRendering;
128 renderNeeded &= !this->GetGlobalImmediateModeRendering( );
130 // Something has changed in the pipeline?
132 this->GetMTime( ) > this->BuildTime ||
133 in->GetMTime( ) > this->BuildTime ||
134 act->GetProperty( )->GetMTime( ) > this->BuildTime ||
135 aren->GetRenderWindow( ) != this->LastWindow
138 // Update visualization objects
139 this->ReleaseGraphicsResources( aren->GetRenderWindow( ) );
140 this->LastWindow = aren->GetRenderWindow( );
146 if( this->ColorTextureMap )
147 this->InternalColorTexture->Load( aren );
150 // Time the actual drawing
151 this->Timer->StartTimer( );
152 noAbort = this->Draw( aren, act );
153 this->Timer->StopTimer( );
158 this->BuildTime.Modified( );
162 // If nothing changed, just draw the mapped mesh
167 if( this->ColorTextureMap )
168 this->InternalColorTexture->Load( aren );
171 // Time the actual drawing
172 this->Timer->StartTimer( );
173 this->Draw( aren, act );
174 this->Timer->StopTimer( );
180 // if we are in immediate mode rendering we always
181 // want to draw the primitives here
186 if( this->ColorTextureMap )
187 this->InternalColorTexture->Load( aren );
190 // Time the actual drawing
191 this->Timer->StartTimer( );
192 this->Draw( aren, act );
193 this->Timer->StopTimer( );
196 this->TimeToDraw = this->Timer->GetElapsedTime( );
198 // If the timer is not accurate enough, set it to a small
199 // time so that it is not zero
200 if( this->TimeToDraw == double( 0 ) )
201 this->TimeToDraw = double( 1e-3 );
203 for( int c = 0; c < numClipPlanes; c++ )
205 GLenum clipPlaneId = static_cast< GLenum >( GL_CLIP_PLANE0 + c );
206 glDisable( clipPlaneId );
209 vtkOpenGLCheckErrorMacro( "failed after RenderPiece\n" );
212 // -------------------------------------------------------------------------
214 void cpm::VTK::OpenGLMeshMapper< M >::
215 ReleaseGraphicsResources( vtkWindow* win )
217 if( win && win->GetMapped( ) )
220 vtkOpenGLCheckErrorMacro( "failed after ReleaseGraphicsResources" );
223 this->LastWindow = NULL;
225 // TAKEN FROM BASIC vtkOpenGLPolyDataMapper:
226 // We may not want to do this here.
228 if( this->InternalColorTexture )
229 this->InternalColorTexture->ReleaseGraphicsResources( win );
233 // -------------------------------------------------------------------------
235 int cpm::VTK::OpenGLMeshMapper< M >::
236 Draw( vtkRenderer* aren, vtkActor* act )
238 vtkOpenGLClearErrorMacro( );
240 // First and second initialization check
241 if( this->FirstRendering )
242 this->FirstRendering = !( this->_ConfigureOpenGL( ) );
243 if( this->FirstRendering )
246 vtkOpenGLRenderer* ren = static_cast< vtkOpenGLRenderer* >( aren );
247 int rep, interpolation;
250 vtkUnsignedCharArray* c = NULL;
253 M* input = this->GetInput( );
255 vtkIdType cellNum = 0;
257 int resolve = 0, zResolve = 0;
261 prop = act->GetProperty( );
263 // get the transparency
264 tran = prop->GetOpacity( );
266 // if the primitives are invisable then get out of here
270 // get the representation ( e.g., surface / wireframe / points )
271 rep = prop->GetRepresentation( );
273 // get the shading interpolation
274 interpolation = prop->GetInterpolation( );
276 // are they cell or point scalars
282 this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_DATA ||
283 this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_FIELD_DATA ||
284 this->ScalarMode == VTK_SCALAR_MODE_USE_FIELD_DATA ||
285 !input->GetPointData( )
287 this->ScalarMode != VTK_SCALAR_MODE_USE_POINT_FIELD_DATA
295 // if we are doing vertex colors then set lmcolor to adjust
296 // the current materials ambient and diffuse values using
297 // vertex color commands otherwise tell it not to.
298 glDisable( GL_COLOR_MATERIAL );
302 if( this->ScalarMaterialMode == VTK_MATERIALMODE_DEFAULT )
304 if( prop->GetAmbient( ) > prop->GetDiffuse( ) )
305 lmcolorMode = GL_AMBIENT;
307 lmcolorMode = GL_DIFFUSE;
309 else if( this->ScalarMaterialMode == VTK_MATERIALMODE_AMBIENT_AND_DIFFUSE )
310 lmcolorMode = GL_AMBIENT_AND_DIFFUSE;
311 else if( this->ScalarMaterialMode == VTK_MATERIALMODE_AMBIENT )
312 lmcolorMode = GL_AMBIENT;
313 else // if( this->ScalarMaterialMode == VTK_MATERIALMODE_DIFFUSE )
314 lmcolorMode = GL_DIFFUSE;
315 glColorMaterial( GL_FRONT_AND_BACK, lmcolorMode );
316 glEnable( GL_COLOR_MATERIAL );
320 unsigned long idx = 0;
323 idx |= CPM_VTK_PDM_COLORS;
325 idx |= CPM_VTK_PDM_OPAQUE_COLORS;
328 idx |= CPM_VTK_PDM_CELL_COLORS;
330 idx |= CPM_VTK_PDM_CELL_NORMALS;
331 if( this->ScalarMode == VTK_SCALAR_MODE_USE_FIELD_DATA )
332 idx |= CPM_VTK_PDM_USE_FIELD_DATA;
334 // store the types in the index
335 if( typeid( typename M::CoordRepType ) == typeid( float ) )
336 idx |= CPM_VTK_PDM_POINT_TYPE_FLOAT;
337 else if( typeid( typename M::CoordRepType ) == typeid( double ) )
338 idx |= CPM_VTK_PDM_POINT_TYPE_DOUBLE;
340 if( typeid( typename M::CoordRepType ) == typeid( float ) )
341 idx |= CPM_VTK_PDM_NORMAL_TYPE_FLOAT;
342 else if( typeid( typename M::CoordRepType ) == typeid( double ) )
343 idx |= CPM_VTK_PDM_NORMAL_TYPE_DOUBLE;
345 if( this->GetResolveCoincidentTopology( ) )
348 if( this->GetResolveCoincidentTopology( ) == VTK_RESOLVE_SHIFT_ZBUFFER )
351 zRes = this->GetResolveCoincidentTopologyZShift( );
355 #ifdef GL_VERSION_1_1
357 glEnable( GL_POLYGON_OFFSET_FILL );
358 this->GetResolveCoincidentTopologyPolygonOffsetParameters( f, u );
359 glPolygonOffset( f, u );
365 // we need to know the total number of cells so that we can
367 this->TotalCells = input->GetNumberOfCells( );
370 if( this->VBOSupported )
372 glBindBuffer( GL_ARRAY_BUFFER, GLuint( this->VBOID1 ) );
374 void* ptr = glMapBuffer( GL_ARRAY_BUFFER, GL_READ_WRITE );
377 // Copy source points to OpenGL buffer
379 input->GetPoints( )->CastToSTLContainer( ).data( );
380 TPoint* dest = reinterpret_cast< TPoint* >( ptr );
382 std::copy( src, src + input->GetNumberOfPoints( ), dest );
383 glUnmapBuffer( GL_ARRAY_BUFFER );
387 std::size_t pSize = input->GetNumberOfPoints( ) * sizeof( TPoint );
389 // Bind vertices, normals and indices
390 glNormalPointer( this->ElementValueType, 0, ( void* )( pSize ) );
391 glVertexPointer( 3, this->ElementValueType, 0, 0 );
392 glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, GLuint( this->VBOID2 ) );
394 // Prepare to render polygons
395 glEnableClientState( GL_NORMAL_ARRAY );
396 glEnableClientState( GL_VERTEX_ARRAY );
398 // Iterate over all input cells
399 unsigned int accum = 0;
400 const TCellsContainer* cells = input->GetCells( );
401 TCellIt cIt = cells->Begin( );
402 for( unsigned int nCell = 0; cIt != cells->End( ); nCell++, cIt++ )
404 const TCell* cell = cIt.Value( );
405 unsigned int nPoints = this->Sizes[ nCell ];
407 // Infere rendering mode
409 switch( prop->GetRepresentation( ) )
415 case 1: mode = GL_POINTS; break;
416 case 2: mode = GL_LINES; break;
417 case 3: mode = GL_TRIANGLES; break;
418 case 4: mode = GL_QUADS; break;
419 default: mode = GL_POLYGON; break;
421 // TODO: GL_LINE_STRIP,
422 // TODO: GL_LINE_LOOP,
423 // TODO: GL_TRIANGLE_STRIP,
424 // TODO: GL_TRIANGLE_FAN,
425 // TODO: GL_QUAD_STRIP,
428 case VTK_WIREFRAME: mode = GL_LINE_LOOP; break;
429 case VTK_POINTS: default: mode = GL_POINTS; break;
432 // Actual draw all elements
434 glDisable( GL_LIGHTING );
436 if( nPoints == 2 && zResolve )
437 glDepthRange( zRes, 1. );
440 mode, nPoints, this->IndexElementType, ( GLuint* )( 0 ) + accum
445 glEnable( GL_LIGHTING );
449 glDisableClientState( GL_VERTEX_ARRAY );
450 glDisableClientState( GL_NORMAL_ARRAY );
452 glBindBuffer( GL_ARRAY_BUFFER, 0 );
453 glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
457 std::cout << "Not VBO rendering!!!" << std::endl;
464 glDepthRange( 0., 1. );
467 #ifdef GL_VERSION_1_1
468 glDisable( GL_POLYGON_OFFSET_FILL );
473 vtkOpenGLCheckErrorMacro( "failed after Draw" );
474 this->UpdateProgress( 1.0 );
478 // -------------------------------------------------------------------------
480 cpm::VTK::OpenGLMeshMapper< M >::
484 FirstRendering( true ),
488 // Infere index element type
489 switch( sizeof( TIndex ) )
491 case 1 : this->IndexElementType = GL_UNSIGNED_BYTE; break;
492 case 2 : this->IndexElementType = GL_UNSIGNED_SHORT; break;
493 case 4 : this->IndexElementType = GL_UNSIGNED_INT; break;
494 default: this->IndexElementType = GL_UNSIGNED_BYTE; break;
497 // Infere point value type
498 if( typeid( TScalar ) == typeid( float ) )
499 this->ElementValueType = GL_FLOAT;
501 this->ElementValueType = GL_DOUBLE;
504 // -------------------------------------------------------------------------
506 cpm::VTK::OpenGLMeshMapper< M >::
509 if( this->LastWindow )
510 this->ReleaseGraphicsResources( this->LastWindow );
511 if( this->VBOSupported )
513 GLuint id1 = GLuint( this->VBOID1 );
514 GLuint id2 = GLuint( this->VBOID2 );
515 if( id1 != GLuint( 0 ) ) glDeleteBuffers( 1, &id1 );
516 if( id2 != GLuint( 0 ) ) glDeleteBuffers( 1, &id2 );
517 this->VBOID1 = this->VBOID2 = 0;
522 // -------------------------------------------------------------------------
524 bool cpm::VTK::OpenGLMeshMapper< M >::
527 M* input = this->GetInput( );
531 // Check if VBO ( Vertex Buffer Object ) is supported
532 std::string str = ( const char* )( glGetString( GL_EXTENSIONS ) );
534 ( str.find( "GL_ARB_vertex_buffer_object" ) != std::string::npos );
536 if( this->VBOSupported )
538 // Create points and normals buffers
540 std::size_t pSize = input->GetNumberOfPoints( ) * sizeof( TPoint );
542 input->GetPointNormalsContainer( ).size( ) * sizeof( TVector );
543 const TPoint* verts =
544 input->GetPoints( )->CastToSTLContainer( ).data( );
545 const TVector* norms = input->GetPointNormalsContainer( ).data( );
546 glGenBuffers( 1, &id1 );
547 glBindBuffer( GL_ARRAY_BUFFER, id1 );
548 glBufferData( GL_ARRAY_BUFFER, pSize + nSize, 0, GL_STREAM_DRAW );
549 glBufferSubData( GL_ARRAY_BUFFER, 0, pSize, verts );
550 glBufferSubData( GL_ARRAY_BUFFER, pSize, nSize, norms );
551 this->VBOID1 = ( unsigned int )( id1 );
553 // Create indices buffer
554 const TCellsContainer* cells = input->GetCells( );
558 << "This QuadEdgeMesh does not have any cells!"
564 unsigned int cellPointsCount = 0;
565 this->Sizes.clear( );
566 for( cIt = cells->Begin( ); cIt != cells->End( ); cIt++ )
568 this->Sizes.push_back( cIt.Value( )->GetNumberOfPoints( ) );
569 cellPointsCount += this->Sizes.back( );
572 this->Indices.resize( cellPointsCount );
573 unsigned int indId = 0;
574 for( cIt = cells->Begin( ); cIt != cells->End( ); cIt++ )
576 const typename M::TQuadEdgeCell* cell =
577 dynamic_cast< const typename M::TQuadEdgeCell* >( cIt.Value( ) );
578 const typename M::TPrimalEdge* edge =
579 cell->GetEntryPrimalEdge( );
580 typename M::TPrimalEdge::ConstIterator iIt = edge->BeginLnext( );
581 for( ; iIt != edge->EndLnext( ); ++iIt )
582 this->Indices[ indId++ ] = ( *iIt )->GetOrigin( );
586 // Attach index buffer to VBO
587 std::size_t iSize = std::size_t( this->Indices.size( ) );
588 iSize *= sizeof( TIndex );
589 const unsigned int* indices = this->Indices.data( );
591 glGenBuffers( 1, &id2 );
592 glBindBuffer( GL_ARRAY_BUFFER, id2 );
593 glBufferData( GL_ARRAY_BUFFER, iSize, indices, GL_STATIC_DRAW );
596 glGetBufferParameteriv( GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &bSize );
599 glDeleteBuffers( 1, &id2 );
601 vtkErrorMacro( << "Data size mismatch with input array" );
604 this->VBOID2 = ( unsigned int )( id2 );
610 // -------------------------------------------------------------------------
611 #include <cpm/DataStructures/QuadEdgeMesh.h>
612 #include <cpm/DataStructures/SimplexMesh.h>
614 using namespace cpm::DataStructures;
615 using namespace cpm::VTK;
617 template class OpenGLMeshMapper< QuadEdgeMesh< float, 2 > >;
618 template class OpenGLMeshMapper< QuadEdgeMesh< float, 3 > >;
619 template class OpenGLMeshMapper< QuadEdgeMesh< double, 2 > >;
620 template class OpenGLMeshMapper< QuadEdgeMesh< double, 3 > >;
622 template class OpenGLMeshMapper< SimplexMesh< float, 2 > >;
623 template class OpenGLMeshMapper< SimplexMesh< float, 3 > >;
624 template class OpenGLMeshMapper< SimplexMesh< double, 2 > >;
625 template class OpenGLMeshMapper< SimplexMesh< double, 3 > >;