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