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