Salome HOME
019350a173c7c91d33ae4fc6946134ebdf04df75
[modules/gui.git] / src / VTKViewer / VTKViewer_PolyDataMapper.cxx
1 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include "VTKViewer_PolyDataMapper.h"
21 #include "VTKViewer_MarkerUtils.h"
22
23 #include <utilities.h>
24
25 #include <QString>
26
27 #include <vtkCellArray.h>
28 #include <vtkImageData.h>
29 #include <vtkObjectFactory.h>
30 #include <vtkPointData.h>
31 #include <vtkPolyData.h>
32 #include <vtkProperty.h>
33 #include <vtkRenderer.h>
34 #include <vtkSmartPointer.h>
35 #include <vtkTimerLog.h>
36 #include <vtkWindow.h>
37
38 #ifndef WNT
39 # ifndef GLX_GLXEXT_LEGACY
40 #  define GLX_GLXEXT_LEGACY
41 # endif
42 # include <GL/glx.h>
43 # include <dlfcn.h>
44 #else
45 # include <wingdi.h>
46 #endif
47
48 #ifndef VTK_IMPLEMENT_MESA_CXX
49 vtkCxxRevisionMacro(VTKViewer_PolyDataMapper, "Revision$");
50 vtkStandardNewMacro(VTKViewer_PolyDataMapper);
51 #endif
52
53 // some definitions for what the polydata has in it
54 #define VTK_PDPSM_COLORS             0x0001
55 #define VTK_PDPSM_CELL_COLORS        0x0002
56 #define VTK_PDPSM_POINT_TYPE_FLOAT   0x0004
57 #define VTK_PDPSM_POINT_TYPE_DOUBLE  0x0008
58 #define VTK_PDPSM_NORMAL_TYPE_FLOAT  0x0010
59 #define VTK_PDPSM_NORMAL_TYPE_DOUBLE 0x0020
60 #define VTK_PDPSM_OPAQUE_COLORS      0x0040
61
62 #ifndef APIENTRY
63 #define APIENTRY
64 #endif
65 #ifndef APIENTRYP
66 #define APIENTRYP APIENTRY *
67 #endif
68
69 #ifndef GL_VERTEX_PROGRAM_POINT_SIZE_ARB
70 #define GL_VERTEX_PROGRAM_POINT_SIZE_ARB  0x8642
71 #endif
72
73 #ifndef GL_ARB_point_sprite
74 #define GL_POINT_SPRITE_ARB               0x8861
75 #define GL_COORD_REPLACE_ARB              0x8862
76 #endif
77
78 #ifndef GL_ARB_vertex_buffer_object
79 typedef ptrdiff_t GLsizeiptrARB;
80
81 #define GL_ARRAY_BUFFER_ARB               0x8892
82 #define GL_STATIC_DRAW_ARB                0x88E4
83 #endif
84
85 typedef void (APIENTRYP PFNGLBINDBUFFERARBPROC) (GLenum target, GLuint buffer);
86 typedef void (APIENTRYP PFNGLDELETEBUFFERSARBPROC) (GLsizei n, const GLuint *buffers);
87 typedef void (APIENTRYP PFNGLGENBUFFERSARBPROC) (GLsizei n, GLuint *buffers);
88 typedef void (APIENTRYP PFNGLBUFFERDATAARBPROC) (GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage);
89
90 static PFNGLGENBUFFERSARBPROC               vglGenBuffersARB              = NULL;
91 static PFNGLBINDBUFFERARBPROC               vglBindBufferARB              = NULL;
92 static PFNGLBUFFERDATAARBPROC               vglBufferDataARB              = NULL;
93 static PFNGLDELETEBUFFERSARBPROC            vglDeleteBuffersARB           = NULL;
94
95 #ifndef WNT
96 #define GL_GetProcAddress( x )   glXGetProcAddressARB( (const GLubyte*)x )
97 #else
98 #define GL_GetProcAddress( x )   wglGetProcAddress( (const LPCSTR)x )
99 #endif
100
101 bool InitializeBufferExtensions()
102 {
103   vglGenBuffersARB = (PFNGLGENBUFFERSARBPROC)GL_GetProcAddress( "glGenBuffersARB" );
104   if( !vglGenBuffersARB )
105     return false;
106
107   vglBindBufferARB = (PFNGLBINDBUFFERARBPROC)GL_GetProcAddress( "glBindBufferARB" );
108   if( !vglBindBufferARB )
109     return false;
110
111   vglBufferDataARB = (PFNGLBUFFERDATAARBPROC)GL_GetProcAddress( "glBufferDataARB" );
112   if( !vglBufferDataARB )
113     return false;
114
115   vglDeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC)GL_GetProcAddress( "glDeleteBuffersARB" );
116   if( !vglDeleteBuffersARB )
117     return false;
118
119   return true;
120 };
121
122 static bool IsBufferExtensionsInitialized = InitializeBufferExtensions();
123
124 //-----------------------------------------------------------------------------
125 VTKViewer_PolyDataMapper::VTKViewer_PolyDataMapper()
126 {
127   Q_INIT_RESOURCE( VTKViewer );
128
129   this->ExtensionsInitialized     = ES_None;
130
131   this->PointSpriteTexture        = 0;
132
133   this->MarkerEnabled             = false;
134   this->MarkerType                = VTK::MT_NONE;
135   this->MarkerScale               = VTK::MS_NONE;
136   this->MarkerId                  = 0;
137 }
138
139 //-----------------------------------------------------------------------------
140 VTKViewer_PolyDataMapper::~VTKViewer_PolyDataMapper()
141 {
142   if( PointSpriteTexture > 0 )
143     glDeleteTextures( 1, &PointSpriteTexture );
144 }
145
146 //-----------------------------------------------------------------------------
147 void VTKViewer_PolyDataMapper::SetMarkerEnabled( bool theMarkerEnabled )
148 {
149   if( this->MarkerEnabled == theMarkerEnabled )
150     return;
151
152   this->MarkerEnabled = theMarkerEnabled;
153   this->Modified();
154 }
155
156 //-----------------------------------------------------------------------------
157 void VTKViewer_PolyDataMapper::SetMarkerStd( VTK::MarkerType theMarkerType, VTK::MarkerScale theMarkerScale )
158 {
159   if( this->MarkerType == theMarkerType && this->MarkerScale == theMarkerScale )
160     return;
161
162   this->MarkerType = theMarkerType;
163   this->MarkerScale = theMarkerScale;
164
165   if( this->MarkerType == VTK::MT_NONE || this->MarkerType == VTK::MT_USER ) {
166     this->ImageData = NULL;
167     this->Modified();
168     return;
169   }
170
171   int aMarkerType = (int)this->MarkerType;
172   int aMarkerScale = (int)this->MarkerScale;
173
174   int anId = (int)VTK::MS_70 * aMarkerType + aMarkerScale;
175
176   if( this->StandardTextures.find( anId ) == this->StandardTextures.end() )
177   {
178     QString aFileName = QString( ":/textures/texture%1.dat" ).arg( aMarkerType );
179     VTK::MarkerTexture aMarkerTexture;
180     if( VTK::LoadTextureData( aFileName, theMarkerScale, aMarkerTexture ) )
181       this->StandardTextures[ anId ] = VTK::MakeVTKImage( aMarkerTexture );
182   }
183
184   this->ImageData = this->StandardTextures[ anId ];
185   this->Modified();
186 }
187
188 //-----------------------------------------------------------------------------
189 void VTKViewer_PolyDataMapper::SetMarkerTexture( int theMarkerId, VTK::MarkerTexture theMarkerTexture )
190 {
191   if( this->MarkerType == VTK::MT_USER && this->MarkerId == theMarkerId )
192     return;
193
194   this->MarkerType = VTK::MT_USER;
195   this->MarkerId = theMarkerId;
196
197   if( this->CustomTextures.find( theMarkerId ) == this->CustomTextures.end() )
198     this->CustomTextures[ theMarkerId ] = VTK::MakeVTKImage( theMarkerTexture );
199
200   this->ImageData = this->CustomTextures[ theMarkerId ];
201   this->Modified();
202 }
203
204 //-----------------------------------------------------------------------------
205 VTK::MarkerType VTKViewer_PolyDataMapper::GetMarkerType()
206 {
207   return this->MarkerType;
208 }
209
210 //-----------------------------------------------------------------------------
211 VTK::MarkerScale VTKViewer_PolyDataMapper::GetMarkerScale()
212 {
213   return this->MarkerScale;
214 }
215
216 //-----------------------------------------------------------------------------
217 int VTKViewer_PolyDataMapper::GetMarkerTexture()
218 {
219   return this->MarkerId;
220 }
221
222 //-----------------------------------------------------------------------------
223 int VTKViewer_PolyDataMapper::InitExtensions()
224 {
225   char* ext = (char*)glGetString( GL_EXTENSIONS );
226   if( !IsBufferExtensionsInitialized ||
227       strstr( ext, "GL_ARB_point_sprite" ) == NULL ||
228       strstr( ext, "GL_ARB_vertex_buffer_object" ) == NULL )
229   {
230     MESSAGE("Initializing ARB extensions failed");
231     return ES_Error;
232   }
233
234   return ES_Ok;
235 }
236
237 //-----------------------------------------------------------------------------
238 void VTKViewer_PolyDataMapper::InitPointSprites()
239 {
240   glEnable( GL_POINT_SPRITE_ARB );
241   glEnable( GL_VERTEX_PROGRAM_POINT_SIZE_ARB );
242
243   glPushAttrib( GL_COLOR_BUFFER_BIT | GL_CURRENT_BIT | GL_DEPTH_BUFFER_BIT | GL_ENABLE_BIT | GL_LIGHTING_BIT );
244
245   glDepthFunc( GL_LEQUAL );
246   glEnable( GL_DEPTH_TEST );
247
248   glEnable( GL_ALPHA_TEST );
249   glAlphaFunc( GL_GREATER, 0.0 );
250
251   glDisable( GL_LIGHTING );
252
253   glDisable( GL_COLOR_MATERIAL );
254 }
255
256 //-----------------------------------------------------------------------------
257 void VTKViewer_PolyDataMapper::CleanupPointSprites()
258 {
259   glPopAttrib();
260
261   glDisable( GL_VERTEX_PROGRAM_POINT_SIZE_ARB );
262   glDisable( GL_POINT_SPRITE_ARB );
263 }
264
265 //-----------------------------------------------------------------------------
266 void VTKViewer_PolyDataMapper::InitTextures()
267 {
268   if( !this->ImageData.GetPointer() )
269     return;
270
271   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
272   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
273   glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
274   glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
275
276   int* aSize = this->ImageData->GetDimensions();
277   unsigned char* dataPtr = (unsigned char*)this->ImageData->GetScalarPointer();
278   glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, aSize[0], aSize[1], 0,
279                 GL_RGBA, GL_UNSIGNED_BYTE, dataPtr );
280
281   //glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
282   glEnable( GL_TEXTURE_2D );
283   glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE );
284   glBindTexture( GL_TEXTURE_2D, this->PointSpriteTexture );
285 }
286
287 //-----------------------------------------------------------------------------
288 void VTKViewer_PolyDataMapper::RenderPiece( vtkRenderer* ren, vtkActor* act )
289 {
290   bool isUsePointSprites = this->MarkerEnabled && this->MarkerType != VTK::MT_NONE;
291   if( isUsePointSprites )
292   {
293     if( this->ExtensionsInitialized == ES_None )
294       this->ExtensionsInitialized = this->InitExtensions();
295     this->InitPointSprites();
296     this->InitTextures();
297   }
298
299   MAPPER_SUPERCLASS::RenderPiece( ren, act );
300
301   if( isUsePointSprites )
302     this->CleanupPointSprites();
303 }
304
305 //-----------------------------------------------------------------------------
306 // Definition of structures and fuctions used in Draw() method
307 namespace VTK
308 {
309   //-----------------------------------------------------------------------------
310   struct TVertex
311   {
312     GLfloat r, g, b, a;
313     GLfloat vx, vy, vz;
314   };
315
316   //-----------------------------------------------------------------------------
317   struct TColorFunctorBase
318   {
319     vtkFloatingPointType myAlpha;
320
321     TColorFunctorBase( vtkProperty* theProperty )
322     {
323       myAlpha = theProperty->GetOpacity();
324     }
325
326     virtual
327     void
328     get( TVertex& theVertex, vtkIdType thePointId, vtkIdType theCellId ) = 0;
329   };
330
331   //-----------------------------------------------------------------------------
332   struct TPropertyColor : TColorFunctorBase
333   {
334     vtkFloatingPointType myColor[3];
335
336     TPropertyColor( vtkProperty* theProperty ):
337       TColorFunctorBase( theProperty )
338     {
339       theProperty->GetColor( myColor );
340     }
341
342     virtual
343     void
344     get( TVertex& theVertex, vtkIdType thePointId, vtkIdType theCellId )
345     {
346       theVertex.r = myColor[0];
347       theVertex.g = myColor[1];
348       theVertex.b = myColor[2];
349       theVertex.a = myAlpha;
350     }
351   };
352
353   //-----------------------------------------------------------------------------
354   struct TColors2Color : TColorFunctorBase
355   {
356     vtkUnsignedCharArray* myColors;
357
358     TColors2Color( vtkProperty* theProperty,
359                    vtkUnsignedCharArray* theColors ):
360       TColorFunctorBase( theProperty ),
361       myColors( theColors )
362     {}
363
364     virtual
365     void
366     get( TVertex& theVertex, vtkIdType thePointId, vtkIdType theCellId )
367     {
368       vtkIdType aTupleId = GetTupleId( thePointId, theCellId );
369       unsigned char* aColor = myColors->GetPointer( aTupleId << 2 );
370
371       theVertex.r = int( aColor[0] ) / 255.0;
372       theVertex.g = int( aColor[1] ) / 255.0;
373       theVertex.b = int( aColor[2] ) / 255.0;
374       theVertex.a = myAlpha;
375     }
376
377     virtual
378     vtkIdType
379     GetTupleId( vtkIdType thePointId, vtkIdType theCellId ) = 0;
380   };
381
382   //-----------------------------------------------------------------------------
383   struct TPointColors2Color : TColors2Color
384   {
385     TPointColors2Color( vtkProperty* theProperty,
386                         vtkUnsignedCharArray* theColors ):
387       TColors2Color( theProperty, theColors )
388     {}
389
390     virtual
391     vtkIdType
392     GetTupleId( vtkIdType thePointId, vtkIdType theCellId )
393     {
394       return thePointId;
395     }
396   };
397
398   //-----------------------------------------------------------------------------
399   struct TCellColors2Color : TColors2Color
400   {
401     TCellColors2Color( vtkProperty* theProperty,
402                        vtkUnsignedCharArray* theColors ):
403       TColors2Color( theProperty, theColors )
404     {}
405
406     virtual
407     vtkIdType
408     GetTupleId( vtkIdType thePointId, vtkIdType theCellId )
409     {
410       return theCellId;
411     }
412   };
413
414   //-----------------------------------------------------------------------------
415   template < class TCoordinates >
416   void DrawPoints( TCoordinates* theStartPoints,
417                    vtkCellArray* theCells,
418                    TColorFunctorBase* theColorFunctor,
419                    TVertex* theVertexArr,
420                    vtkIdType &theCellId,
421                    vtkIdType &theVertexId )
422   {
423     vtkIdType* ptIds = theCells->GetPointer();
424     vtkIdType* endPtIds = ptIds + theCells->GetNumberOfConnectivityEntries();
425
426     while ( ptIds < endPtIds ) {
427       vtkIdType nPts = *ptIds;
428       ++ptIds;
429
430       while ( nPts > 0 ) {
431         TVertex& aVertex = theVertexArr[ theVertexId ];
432         vtkIdType aPointId = *ptIds;
433
434         TCoordinates* anOffsetPoints = theStartPoints + 3 * aPointId;
435         aVertex.vx = anOffsetPoints[0];
436         aVertex.vy = anOffsetPoints[1];
437         aVertex.vz = anOffsetPoints[2];
438
439         theColorFunctor->get( aVertex, aPointId, theCellId );
440
441         ++theVertexId;
442         ++ptIds; 
443         --nPts; 
444       }
445
446       ++theCellId;
447     }
448   }
449
450   //-----------------------------------------------------------------------------
451   template < class TCoordinates >
452   void DrawCellsPoints( vtkPolyData* theInput,
453                         vtkPoints* thePoints,
454                         TColorFunctorBase* theColorFunctor,
455                         TVertex* theVertexArr )
456   {
457     vtkIdType aCellId = 0, aVertexId = 0;
458
459     TCoordinates* aStartPoints = (TCoordinates*)thePoints->GetVoidPointer(0);
460
461     if ( vtkCellArray* aCellArray = theInput->GetVerts() )
462       DrawPoints( aStartPoints, aCellArray, theColorFunctor, theVertexArr, aCellId, aVertexId );
463   
464     if ( vtkCellArray* aCellArray = theInput->GetLines() )
465       DrawPoints( aStartPoints, aCellArray, theColorFunctor, theVertexArr, aCellId, aVertexId );
466   
467     if ( vtkCellArray* aCellArray = theInput->GetPolys() )
468       DrawPoints( aStartPoints, aCellArray, theColorFunctor, theVertexArr, aCellId, aVertexId );
469   
470     if ( vtkCellArray* aCellArray = theInput->GetStrips() )
471       DrawPoints( aStartPoints, aCellArray, theColorFunctor, theVertexArr, aCellId, aVertexId ); 
472   }
473 } // namespace VTK
474
475 //-----------------------------------------------------------------------------
476 int VTKViewer_PolyDataMapper::Draw( vtkRenderer* ren, vtkActor* act )
477 {
478   if( !this->MarkerEnabled || this->MarkerType == VTK::MT_NONE || !this->ImageData.GetPointer() )
479     return MAPPER_SUPERCLASS::Draw( ren, act );
480
481   vtkUnsignedCharArray* colors = NULL;
482   vtkPolyData* input  = this->GetInput();
483   vtkPoints* points;
484   int noAbort = 1;
485   int cellScalars = 0;
486   vtkProperty* prop = act->GetProperty();
487
488   points = input->GetPoints();
489
490   if ( this->Colors )
491   {
492     colors = this->Colors;
493     if ( (this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_DATA ||
494           this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_FIELD_DATA ||
495           !input->GetPointData()->GetScalars() )
496          && this->ScalarMode != VTK_SCALAR_MODE_USE_POINT_FIELD_DATA)
497       cellScalars = 1;
498   }
499
500   {
501     vtkIdType aTotalConnectivitySize = 0;
502
503     if ( vtkCellArray* aCellArray = input->GetVerts() )
504       aTotalConnectivitySize += aCellArray->GetNumberOfConnectivityEntries() - aCellArray->GetNumberOfCells();
505
506     if ( vtkCellArray* aCellArray = input->GetLines() )
507       aTotalConnectivitySize += aCellArray->GetNumberOfConnectivityEntries() - aCellArray->GetNumberOfCells();
508
509     if ( vtkCellArray* aCellArray = input->GetPolys() )
510       aTotalConnectivitySize += aCellArray->GetNumberOfConnectivityEntries() - aCellArray->GetNumberOfCells();
511
512     if ( vtkCellArray* aCellArray = input->GetStrips() )
513       aTotalConnectivitySize += aCellArray->GetNumberOfConnectivityEntries() - aCellArray->GetNumberOfCells();
514
515     if ( aTotalConnectivitySize > 0 ) {
516       VTK::TVertex* aVertexArr = new VTK::TVertex[ aTotalConnectivitySize ];
517
518       int* aSize = this->ImageData->GetDimensions();
519       glPointSize( std::max( aSize[0], aSize[1] ) );
520
521       int aMode = 0; // to remove
522       {
523         VTK::TColorFunctorBase* aColorFunctor = NULL;
524         if( colors && aMode != 1 ) {
525           if ( cellScalars )
526             aColorFunctor = new VTK::TCellColors2Color( prop, colors );
527           else
528             aColorFunctor = new VTK::TPointColors2Color( prop, colors );
529         } else {
530           aColorFunctor = new VTK::TPropertyColor( prop );
531         }
532         if ( points->GetDataType() == VTK_FLOAT )
533           VTK::DrawCellsPoints< float >( input, points, aColorFunctor, aVertexArr );
534         else
535           VTK::DrawCellsPoints< double >( input, points, aColorFunctor, aVertexArr );
536
537         delete aColorFunctor;
538       }
539
540       if( this->ExtensionsInitialized == ES_Ok ) {
541         GLuint aBufferObjectID = 0;
542         vglGenBuffersARB( 1, &aBufferObjectID );
543         vglBindBufferARB( GL_ARRAY_BUFFER_ARB, aBufferObjectID );
544         
545         int anArrayObjectSize = sizeof( VTK::TVertex ) * aTotalConnectivitySize;
546         vglBufferDataARB( GL_ARRAY_BUFFER_ARB, anArrayObjectSize, aVertexArr, GL_STATIC_DRAW_ARB );
547         
548         delete [] aVertexArr;
549         
550         vglBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 );
551         vglBindBufferARB( GL_ARRAY_BUFFER_ARB, aBufferObjectID );
552         
553         glColorPointer( 4, GL_FLOAT, sizeof(VTK::TVertex), (void*)0 );
554         glVertexPointer( 3, GL_FLOAT, sizeof(VTK::TVertex), (void*)(4*sizeof(GLfloat)) );
555         
556         glEnableClientState( GL_VERTEX_ARRAY );
557         glEnableClientState( GL_COLOR_ARRAY );
558         
559         glDrawArrays( GL_POINTS, 0, aTotalConnectivitySize );
560         
561         glDisableClientState( GL_COLOR_ARRAY );
562         glDisableClientState( GL_VERTEX_ARRAY );
563         
564         vglDeleteBuffersARB( 1, &aBufferObjectID );
565       } else { // there are no extensions
566         glColorPointer( 4, GL_FLOAT, sizeof(VTK::TVertex), aVertexArr );
567         glVertexPointer( 3, GL_FLOAT, sizeof(VTK::TVertex), 
568                          (void*)((GLfloat*)((void*)(aVertexArr)) + 4));
569
570         glEnableClientState( GL_VERTEX_ARRAY );
571         glEnableClientState( GL_COLOR_ARRAY );
572         
573         glDrawArrays( GL_POINTS, 0, aTotalConnectivitySize );
574         
575         glDisableClientState( GL_COLOR_ARRAY );
576         glDisableClientState( GL_VERTEX_ARRAY );
577
578         delete [] aVertexArr;
579       }
580     }
581   }
582
583   this->UpdateProgress(1.0);
584   return noAbort;
585 }