Salome HOME
84f3dd8e6bd6663f3e4f965da4e6a984a9df079c
[modules/gui.git] / src / VTKViewer / VTKViewer_PolyDataMapper.cxx
1 // Copyright (C) 2007-2016  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, or (at your option) any later version.
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 #ifdef VTK_OPENGL2
20 #define GL_GLEXT_PROTOTYPES
21 #endif
22
23 #include "VTKViewer_PolyDataMapper.h"
24 #include "VTKViewer_MarkerUtils.h"
25
26 #include <utilities.h>
27
28 #include <QString>
29
30 #include <vtkCellArray.h>
31 #include <vtkXMLImageDataReader.h>
32 #include <vtkImageData.h>
33 #include <vtkObjectFactory.h>
34 #include <vtkPointData.h>
35 #include <vtkPolyData.h>
36 #include <vtkProperty.h>
37 #include <vtkRenderer.h>
38 #include <vtkSmartPointer.h>
39 #include <vtkTimerLog.h>
40 #include <vtkWindow.h>
41 #include <vtkRenderWindow.h>
42 #include <vtkCommand.h>
43 #include <vtkCellData.h>
44
45 #ifndef WIN32
46 # ifndef GLX_GLXEXT_LEGACY
47 #  define GLX_GLXEXT_LEGACY
48 # endif
49 #ifdef __APPLE__
50 #import <mach-o/dyld.h>
51 #import <stdlib.h>
52 #import <string.h>
53 void * glXGetProcAddressARB (const GLubyte *name)
54
55 {
56     NSSymbol symbol;
57     char *symbolName;
58     symbolName = (char *)malloc (strlen ((const char *)name) + 2); // 1
59     strcpy(symbolName + 1, (const char *)name); // 2
60     symbolName[0] = '_'; // 3
61     symbol = NULL;
62     if (NSIsSymbolNameDefined (symbolName)) // 4
63         symbol = NSLookupAndBindSymbol (symbolName);
64     free (symbolName); // 5
65     return symbol ? NSAddressOfSymbol (symbol) : NULL; // 6
66 }
67 #else
68 # include <GL/glx.h>
69 #endif
70 # include <dlfcn.h>
71 #else
72 # include <wingdi.h>
73 #endif
74
75 #ifndef VTK_IMPLEMENT_MESA_CXX
76 vtkStandardNewMacro(VTKViewer_PolyDataMapper);
77 #endif
78
79 // some definitions for what the polydata has in it
80 #define VTK_PDPSM_COLORS             0x0001
81 #define VTK_PDPSM_CELL_COLORS        0x0002
82 #define VTK_PDPSM_POINT_TYPE_FLOAT   0x0004
83 #define VTK_PDPSM_POINT_TYPE_DOUBLE  0x0008
84 #define VTK_PDPSM_NORMAL_TYPE_FLOAT  0x0010
85 #define VTK_PDPSM_NORMAL_TYPE_DOUBLE 0x0020
86 #define VTK_PDPSM_OPAQUE_COLORS      0x0040
87
88 typedef GLfloat TBall;
89
90 #ifdef WIN32
91   #ifdef max
92     #undef max
93   #endif
94 #endif
95
96 // ----------------------------------------------- Special Textures -----------------------------------
97 // texture id for balls drawing
98 #define BallTextureId 0 
99
100
101
102 void MessageCallback( GLenum source,
103                       GLenum type,
104                       GLuint id,
105                       GLenum severity,
106                       GLsizei length,
107                       const GLcharARB* message,
108                       const void* userParam )
109 {
110   fprintf( stderr, "GL CALLBACK: %s type = 0x%x, severity = 0x%x, message = %s\n",
111            ( type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : "" ),
112             type, severity, message );
113 }
114
115
116 //-----------------------------------------------------------------------------
117 VTKViewer_PolyDataMapper::VTKViewer_PolyDataMapper()
118 {
119   Q_INIT_RESOURCE( VTKViewer );
120
121   this->ExtensionsInitialized     = ES_None;
122
123   this->PointSpriteTexture        = 0;
124
125   this->MarkerEnabled             = false;
126   this->MarkerType                = VTK::MT_NONE;
127   this->MarkerScale               = VTK::MS_NONE;
128   this->MarkerId                  = 0;
129   this->BallEnabled               = false;
130   this->BallScale                 = 1.0;
131   this->PointProgram              = 0;
132 #ifdef VTK_OPENGL2
133   this->VertexShader              = 0;
134   this->FragmentShader            = 0;
135 #endif
136
137   this->OpenGLHelper.Init();
138
139   // For debug purposes only
140   // glEnable              ( GL_DEBUG_OUTPUT );
141   // glDebugMessageCallback( (GLDEBUGPROC) MessageCallback, 0 );
142
143 }
144
145 //-----------------------------------------------------------------------------
146 VTKViewer_PolyDataMapper::~VTKViewer_PolyDataMapper()
147 {
148   if( PointSpriteTexture > 0 )
149     glDeleteTextures( 1, &PointSpriteTexture );
150
151 #ifdef VTK_OPENGL2
152   this->OpenGLHelper.DestroyShaderProgram( this->PointProgram, this->VertexShader, this->FragmentShader);
153 #endif
154 }
155
156 //-----------------------------------------------------------------------------
157 int VTKViewer_PolyDataMapper::InitShader()
158 {
159 #ifdef VTK_OPENGL2
160   std::string filePath = std::string( getenv( "GUI_ROOT_DIR") ) + "/share/salome/resources/gui/Point";
161   if( !this->OpenGLHelper.CreateShaderProgram(filePath, this->PointProgram, this->VertexShader, this->FragmentShader) )
162     return false;
163
164   // Get uniform locations.
165   GLint current_program;
166   glGetIntegerv( GL_CURRENT_PROGRAM, &current_program );
167   this->OpenGLHelper.vglUseProgramObjectARB( this->PointProgram );
168
169   this->myLocations.ModelViewProjection = this->OpenGLHelper.vglGetUniformLocationARB( this->PointProgram, "uModelViewProjectionMatrix" );
170   this->myLocations.Projection          = this->OpenGLHelper.vglGetUniformLocationARB( this->PointProgram, "uProjectionMatrix" );
171   this->myLocations.GeneralPointSize    = this->OpenGLHelper.vglGetUniformLocationARB( this->PointProgram, "uGeneralPointSize" );
172   this->myLocations.PointSprite         = this->OpenGLHelper.vglGetUniformLocationARB( this->PointProgram, "uPointSprite" );
173
174   this->OpenGLHelper.vglUseProgramObjectARB( current_program );
175
176   this->OpenGLHelper.vglGenVertexArraysARB(1, &this->VertexArrayObject);
177 #else
178   std::string fileName = std::string( getenv( "GUI_ROOT_DIR") ) +
179                          "/share/salome/resources/gui/Vertex_Program_ARB.txt";
180
181   char* shader = GUI_OPENGL::readFromFile( fileName );
182
183   GLhandleARB VertexShader = this->OpenGLHelper.vglCreateShaderObjectARB( GL_VERTEX_SHADER_ARB );
184   this->OpenGLHelper.vglShaderSourceARB( VertexShader, 1, (const GLcharARB**)&shader, NULL );
185   this->OpenGLHelper.vglCompileShaderARB( VertexShader );
186
187   this->PointProgram = this->OpenGLHelper.vglCreateProgramObjectARB();
188   this->OpenGLHelper.vglAttachObjectARB( this->PointProgram, VertexShader );
189
190   this->OpenGLHelper.vglLinkProgramARB( this->PointProgram );
191   free( shader );
192 #endif
193
194   return ES_Ok;
195 }
196
197
198 //-----------------------------------------------------------------------------
199 void VTKViewer_PolyDataMapper::SetMarkerEnabled( bool theMarkerEnabled )
200 {
201   if( this->MarkerEnabled == theMarkerEnabled )
202     return;
203
204   this->MarkerEnabled = theMarkerEnabled;
205   this->Modified();
206 }
207
208 //-----------------------------------------------------------------------------
209 // Definition of structures and fuctions used in SetBallEnabled() method
210 namespace VTK
211 {
212   //----------------------------------------------------------------------------
213   vtkSmartPointer<vtkImageData> MakeTexture( const char* theMainTexture, const char* theAlphaTexture ) {
214     if( !theMainTexture || !theAlphaTexture )
215       return 0;
216     
217     vtkXMLImageDataReader* aMainReader = vtkXMLImageDataReader::New();
218     vtkXMLImageDataReader* anAlphaReader = vtkXMLImageDataReader::New();
219     
220     aMainReader->SetFileName( theMainTexture );
221     anAlphaReader->SetFileName( theAlphaTexture );
222
223     aMainReader->Update();
224     anAlphaReader->Update();
225     
226     vtkImageData* aMainImageData = aMainReader->GetOutput();
227     vtkImageData* anAlphaImageData = anAlphaReader->GetOutput();
228     
229     int* aMainImageSize = aMainImageData->GetDimensions();
230     int* anAlphaImageSize = anAlphaImageData->GetDimensions();
231     if(aMainImageSize[0] != anAlphaImageSize[0] || aMainImageSize[1] != anAlphaImageSize[1])
232       return NULL;
233
234     vtkSmartPointer<vtkImageData> aCompositeImageData = vtkImageData::New();
235     aCompositeImageData->Delete();
236     
237     int aNbCompositeComponents = 4;
238     aCompositeImageData->SetDimensions(aMainImageSize);
239     aCompositeImageData->AllocateScalars( VTK_UNSIGNED_CHAR, aNbCompositeComponents );
240     
241     unsigned char* aMainDataPtr = (unsigned char*)aMainImageData->GetScalarPointer();
242     unsigned char* anAlphaDataPtr = (unsigned char*)anAlphaImageData->GetScalarPointer();
243     unsigned char *aCompositeDataPtr = (unsigned char * )aCompositeImageData->GetScalarPointer();
244
245     int aNbMainComponents = aMainImageData->GetNumberOfScalarComponents();
246     int aNbAlphaComponents = anAlphaImageData->GetNumberOfScalarComponents();
247     int aCompositeSize = aMainImageSize[0] * aMainImageSize[1] * aNbCompositeComponents;
248
249     int aMainId = 0, anAlphaId = 0, aCompositeId = 0;
250     for(; aCompositeId < aCompositeSize;) {
251       aCompositeDataPtr[aCompositeId] = aMainDataPtr[aMainId];
252       aCompositeDataPtr[aCompositeId + 1] = aMainDataPtr[aMainId + 1];
253       aCompositeDataPtr[aCompositeId + 2] = aMainDataPtr[aMainId + 2];
254       aCompositeDataPtr[aCompositeId + 3] = anAlphaDataPtr[anAlphaId];
255
256       aMainId += aNbMainComponents;
257       anAlphaId += aNbAlphaComponents;
258       aCompositeId += aNbCompositeComponents;
259     }
260     aMainReader->Delete();
261     anAlphaReader->Delete();
262     return aCompositeImageData;
263   }  
264 }
265
266 //-----------------------------------------------------------------------------
267 bool VTKViewer_PolyDataMapper::GetBallEnabled()
268 {
269   return this->BallEnabled;
270 }
271 //-----------------------------------------------------------------------------
272 void VTKViewer_PolyDataMapper::SetBallEnabled( bool theBallEnabled )
273
274   if( this->BallEnabled == theBallEnabled )
275     return;
276   else 
277     this->BallEnabled = theBallEnabled;
278
279   if(!this->BallEnabled) {
280     this->ImageData = NULL;
281   }
282
283   if(this->BallEnabled) {
284     if(this->SpecialTextures.find(BallTextureId) == SpecialTextures.end()){
285       QString aMainTexture  = getenv( "GUI_ROOT_DIR" );
286       aMainTexture.append("/share/salome/resources/gui/sprite_texture.vti");
287       
288       QString anAlphaTexture = getenv( "GUI_ROOT_DIR" );
289       anAlphaTexture.append( "/share/salome/resources/gui/sprite_alpha.vti" );
290       vtkSmartPointer<vtkImageData> aTextureValue = VTK::MakeTexture( aMainTexture.toUtf8().constData(), anAlphaTexture.toUtf8().constData() );
291       this->SpecialTextures[BallTextureId] = aTextureValue;
292     }
293     this->ImageData = this->SpecialTextures[BallTextureId];
294   }
295   this->Modified();
296 }
297
298 //-----------------------------------------------------------------------------
299 double VTKViewer_PolyDataMapper::GetBallScale()
300 {
301   return this->BallScale;
302 }
303 //-----------------------------------------------------------------------------
304 void VTKViewer_PolyDataMapper::SetBallScale( double theBallScale )
305 {
306   if( this->BallScale == theBallScale )
307     return;
308   this->BallScale = theBallScale;
309 }
310
311 //-----------------------------------------------------------------------------
312 void VTKViewer_PolyDataMapper::SetMarkerStd( VTK::MarkerType theMarkerType, VTK::MarkerScale theMarkerScale )
313 {
314   if( this->MarkerType == theMarkerType && this->MarkerScale == theMarkerScale )
315     return;
316
317   this->MarkerType = theMarkerType;
318   this->MarkerScale = theMarkerScale;
319
320   if( this->MarkerType == VTK::MT_NONE || this->MarkerType == VTK::MT_USER ) {
321     this->ImageData = NULL;
322     this->Modified();
323     return;
324   }
325
326   int aMarkerType = (int)this->MarkerType;
327   int aMarkerScale = (int)this->MarkerScale;
328
329   int anId = (int)VTK::MS_70 * aMarkerType + aMarkerScale;
330
331   if( this->StandardTextures.find( anId ) == this->StandardTextures.end() )
332   {
333     QString aFileName = QString( ":/textures/texture%1.dat" ).arg( aMarkerType );
334     VTK::MarkerTexture aMarkerTexture;
335     if( VTK::LoadTextureData( aFileName, theMarkerScale, aMarkerTexture ) )
336       this->StandardTextures[ anId ] = VTK::MakeVTKImage( aMarkerTexture );
337   }
338
339   this->ImageData = this->StandardTextures[ anId ];
340   this->Modified();
341 }
342
343 //-----------------------------------------------------------------------------
344 void VTKViewer_PolyDataMapper::SetMarkerTexture( int theMarkerId, VTK::MarkerTexture theMarkerTexture )
345 {
346   if( this->MarkerType == VTK::MT_USER && this->MarkerId == theMarkerId )
347     return;
348
349   this->MarkerType = VTK::MT_USER;
350   this->MarkerId = theMarkerId;
351
352   if( this->CustomTextures.find( theMarkerId ) == this->CustomTextures.end() )
353     this->CustomTextures[ theMarkerId ] = VTK::MakeVTKImage( theMarkerTexture );
354
355   this->ImageData = this->CustomTextures[ theMarkerId ];
356   this->Modified();
357 }
358
359 //-----------------------------------------------------------------------------
360 VTK::MarkerType VTKViewer_PolyDataMapper::GetMarkerType()
361 {
362   return this->MarkerType;
363 }
364
365 //-----------------------------------------------------------------------------
366 VTK::MarkerScale VTKViewer_PolyDataMapper::GetMarkerScale()
367 {
368   return this->MarkerScale;
369 }
370
371 //-----------------------------------------------------------------------------
372 int VTKViewer_PolyDataMapper::GetMarkerTexture()
373 {
374   return this->MarkerId;
375 }
376
377 //-----------------------------------------------------------------------------
378 int VTKViewer_PolyDataMapper::InitExtensions()
379 {
380 #ifdef VTK_OPENGL2
381   int n = 0;
382   std::ostringstream strm;
383   glGetIntegerv(GL_NUM_EXTENSIONS, &n);
384   for (int i = 0; i < n; i++)
385     {
386       const char *exti = (const char *)this->OpenGLHelper.vglGetStringiARB(GL_EXTENSIONS, i);
387       strm<< exti <<" ";
388     }
389   std::string s = strm.str();
390   const char* ext = s.c_str();
391 #else  
392   const char* ext = (const char*)glGetString( GL_EXTENSIONS );
393 #endif
394   if( !this->OpenGLHelper.IsInitialized() || !ext ||
395       strstr( ext, "GL_ARB_point_sprite" ) == NULL ||
396       strstr( ext, "GL_ARB_vertex_buffer_object" ) == NULL ||
397       strstr( ext, "GL_ARB_shader_objects") == NULL )
398   {
399     MESSAGE("Initializing ARB extensions failed");
400     return ES_Error;
401   }
402
403   return this->InitShader();
404 }
405
406 //-----------------------------------------------------------------------------
407 void VTKViewer_PolyDataMapper::InitPointSprites()
408 {
409   glEnable( GL_POINT_SPRITE_ARB );
410   glEnable( GL_VERTEX_PROGRAM_POINT_SIZE_ARB );
411
412   glPushAttrib( GL_COLOR_BUFFER_BIT | GL_CURRENT_BIT | GL_DEPTH_BUFFER_BIT | GL_ENABLE_BIT | GL_LIGHTING_BIT );
413
414   glDepthFunc( GL_LEQUAL );
415   glEnable( GL_DEPTH_TEST );
416
417   glEnable( GL_ALPHA_TEST );
418   if(!this->BallEnabled) {
419     glAlphaFunc( GL_GREATER, 0.0 );
420   }
421   else { 
422     glAlphaFunc( GL_GREATER, 0.5 );
423   }
424
425   glDisable( GL_LIGHTING );
426
427   glDisable( GL_COLOR_MATERIAL );
428 }
429
430 //-----------------------------------------------------------------------------
431 void VTKViewer_PolyDataMapper::CleanupPointSprites()
432 {
433   glPopAttrib();
434
435   glDisable( GL_VERTEX_PROGRAM_POINT_SIZE_ARB );
436   glDisable( GL_POINT_SPRITE_ARB );
437 }
438
439 //-----------------------------------------------------------------------------
440 void VTKViewer_PolyDataMapper::InitTextures()
441 {
442   if( !this->ImageData.GetPointer() )
443     return;
444
445   glEnable( GL_TEXTURE_2D );
446   if( this->PointSpriteTexture == 0 ) {
447     glGenTextures( 1, &this->PointSpriteTexture );
448   }
449 #ifdef VTK_OPENGL2
450   this->OpenGLHelper.vglActiveTextureARB( GL_TEXTURE0 );
451 #endif
452   glBindTexture( GL_TEXTURE_2D, this->PointSpriteTexture );
453   glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE );
454   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
455   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
456   
457   if(this->BallEnabled) {
458     glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
459     glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
460   } else {
461     glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
462     glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
463   }
464
465   int* aSize = this->ImageData->GetDimensions();
466   unsigned char* dataPtr = (unsigned char*)this->ImageData->GetScalarPointer();
467   glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, aSize[0], aSize[1], 0,
468                 GL_RGBA, GL_UNSIGNED_BYTE, dataPtr );
469
470 #ifdef VTK_OPENGL2
471   // Set sampler.
472   this->OpenGLHelper.vglUniform1iARB( this->myLocations.PointSprite, GL_TEXTURE0 );
473 #endif
474 }
475
476 //-----------------------------------------------------------------------------
477 void VTKViewer_PolyDataMapper::RenderPiece( vtkRenderer* ren, vtkActor* act )
478 {
479   bool isUsePointSprites = (this->MarkerEnabled && this->MarkerType != VTK::MT_NONE) || 
480     this->BallEnabled;
481   if( isUsePointSprites )
482   {
483     if( this->ExtensionsInitialized != ES_Ok )
484       this->ExtensionsInitialized = this->InitExtensions();
485     this->InitPointSprites();
486     this->InitTextures();
487   }
488
489   if(!this->BallEnabled || this->ExtensionsInitialized != ES_Ok) {
490     MAPPER_SUPERCLASS::RenderPiece( ren, act );
491     if( isUsePointSprites )
492       this->CleanupPointSprites();
493     glBindTexture( GL_TEXTURE_2D, 0 );
494   } else {
495     vtkIdType numPts;
496     vtkPolyData *input= this->GetInput();
497
498     //
499     // make sure that we've been properly initialized
500     //
501     if (ren->GetRenderWindow()->CheckAbortStatus())
502       return;
503
504     if ( input == NULL )
505     {
506       vtkErrorMacro(<< "No input!");
507       return;
508     }
509     else
510     {
511       this->InvokeEvent(vtkCommand::StartEvent,NULL);
512       this->Update();
513       this->InvokeEvent(vtkCommand::EndEvent,NULL);
514       numPts = input->GetNumberOfPoints();
515     }
516
517     if (numPts == 0)
518     {
519       vtkDebugMacro(<< "No points!");
520       return;
521     }
522
523     // make sure our window is current
524     ren->GetRenderWindow()->MakeCurrent();
525
526     GLint current_program;
527     glGetIntegerv( GL_CURRENT_PROGRAM, &current_program );
528     this->OpenGLHelper.vglUseProgramObjectARB( this->PointProgram );
529
530 #ifndef VTK_OPENGL2
531     //
532     // if something has changed regenerate colors and display lists
533     // if required
534     //
535     int noAbort=1;
536     if ( this->GetMTime() > this->BuildTime ||
537          input->GetMTime() > this->BuildTime ||
538          act->GetProperty()->GetMTime() > this->BuildTime ||
539          ren->GetRenderWindow() != this->LastWindow)
540     {
541       // sets this->Colors as side effect
542       this->MapScalars( act->GetProperty()->GetOpacity() );
543
544       if (!this->ImmediateModeRendering &&
545           !this->GetGlobalImmediateModeRendering())
546       {
547         this->ReleaseGraphicsResources(ren->GetRenderWindow());
548         this->LastWindow = ren->GetRenderWindow();
549
550         // get a unique display list id
551         this->ListId = glGenLists(1);
552         glNewList(this->ListId,GL_COMPILE);
553
554         noAbort = this->Draw(ren,act);
555         glEndList();
556
557         // Time the actual drawing
558         this->Timer->StartTimer();
559         glCallList(this->ListId);
560         this->Timer->StopTimer();
561       }
562       else
563       {
564         this->ReleaseGraphicsResources(ren->GetRenderWindow());
565         this->LastWindow = ren->GetRenderWindow();
566       }
567       if (noAbort)
568         this->BuildTime.Modified();
569     }
570     // if nothing changed but we are using display lists, draw it
571     else
572     {
573       if (!this->ImmediateModeRendering &&
574           !this->GetGlobalImmediateModeRendering())
575       {
576         // Time the actual drawing
577         this->Timer->StartTimer();
578         glCallList(this->ListId);
579         this->Timer->StopTimer();
580       }
581     }
582
583     // if we are in immediate mode rendering we always
584     // want to draw the primitives here
585     if (this->ImmediateModeRendering ||
586         this->GetGlobalImmediateModeRendering())
587     {
588       // sets this->Colors as side effect
589       this->MapScalars( act->GetProperty()->GetOpacity() );
590
591       // Time the actual drawing
592       this->Timer->StartTimer();
593       this->Draw(ren,act);
594       this->Timer->StopTimer();
595     }
596
597     this->TimeToDraw = (float)this->Timer->GetElapsedTime();
598
599     // If the timer is not accurate enough, set it to a small
600     // time so that it is not zero
601     if ( this->TimeToDraw == 0.0 )
602       this->TimeToDraw = 0.0001;
603 #else
604     //this->RenderPieceStart(ren, act);
605     this->RenderPieceDraw(ren, act);
606     //    this->RenderEdges(ren,act);
607     //this->RenderPieceFinish(ren, act);
608 #endif    
609     this->OpenGLHelper.vglUseProgramObjectARB( current_program );
610     this->CleanupPointSprites();
611     glBindTexture( GL_TEXTURE_2D, 0 );
612   }  
613 }
614
615 //-----------------------------------------------------------------------------
616 // Definition of structures and fuctions used in Draw() method
617 namespace VTK
618 {
619   //-----------------------------------------------------------------------------
620   struct TVertex
621   {
622     GLfloat r, g, b, a;
623     GLfloat vx, vy, vz;
624   };
625
626   //-----------------------------------------------------------------------------
627   struct TColorFunctorBase
628   {
629     double myAlpha;
630
631     TColorFunctorBase( vtkProperty* theProperty )
632     {
633       myAlpha = theProperty->GetOpacity();
634     }
635
636     virtual
637     void
638     get( TVertex& theVertex, vtkIdType thePointId, vtkIdType theCellId ) = 0;
639
640     virtual ~TColorFunctorBase() {}
641   };
642
643   //-----------------------------------------------------------------------------
644   struct TPropertyColor : TColorFunctorBase
645   {
646     double myColor[3];
647
648     TPropertyColor( vtkProperty* theProperty ):
649       TColorFunctorBase( theProperty )
650     {
651       theProperty->GetColor( myColor );
652     }
653
654     virtual
655     void
656     get( TVertex& theVertex, vtkIdType thePointId, vtkIdType theCellId )
657     {
658       theVertex.r = myColor[0];
659       theVertex.g = myColor[1];
660       theVertex.b = myColor[2];
661       theVertex.a = myAlpha;
662     }
663   };
664
665   //-----------------------------------------------------------------------------
666   struct TColors2Color : TColorFunctorBase
667   {
668     vtkUnsignedCharArray* myColors;
669
670     TColors2Color( vtkProperty* theProperty,
671                    vtkUnsignedCharArray* theColors ):
672       TColorFunctorBase( theProperty ),
673       myColors( theColors )
674     {}
675
676     virtual
677     void
678     get( TVertex& theVertex, vtkIdType thePointId, vtkIdType theCellId )
679     {
680       vtkIdType aTupleId = GetTupleId( thePointId, theCellId );
681       unsigned char* aColor = myColors->GetPointer( aTupleId << 2 );
682
683       theVertex.r = int( aColor[0] ) / 255.0;
684       theVertex.g = int( aColor[1] ) / 255.0;
685       theVertex.b = int( aColor[2] ) / 255.0;
686       theVertex.a = myAlpha;
687     }
688
689     virtual
690     vtkIdType
691     GetTupleId( vtkIdType thePointId, vtkIdType theCellId ) = 0;
692   };
693
694   //-----------------------------------------------------------------------------
695   struct TPointColors2Color : TColors2Color
696   {
697     TPointColors2Color( vtkProperty* theProperty,
698                         vtkUnsignedCharArray* theColors ):
699       TColors2Color( theProperty, theColors )
700     {}
701
702     virtual
703     vtkIdType
704     GetTupleId( vtkIdType thePointId, vtkIdType theCellId )
705     {
706       return thePointId;
707     }
708   };
709
710   //-----------------------------------------------------------------------------
711   struct TCellColors2Color : TColors2Color
712   {
713     TCellColors2Color( vtkProperty* theProperty,
714                        vtkUnsignedCharArray* theColors ):
715       TColors2Color( theProperty, theColors )
716     {}
717
718     virtual
719     vtkIdType
720     GetTupleId( vtkIdType thePointId, vtkIdType theCellId )
721     {
722       return theCellId;
723     }
724   };
725
726   //-----------------------------------------------------------------------------
727   template < class TCoordinates >
728   void DrawPoints( TCoordinates* theStartPoints,
729                    vtkCellArray* theCells,
730                    TColorFunctorBase* theColorFunctor,
731                    TVertex* theVertexArr,
732                    vtkIdType &theCellId,
733                    vtkIdType &theVertexId,
734                    TBall* theBallArr,
735                    vtkDataArray* theDiamArray,
736                    double theBallScale )
737   {
738     vtkIdType* ptIds = theCells->GetPointer();
739     vtkIdType* endPtIds = ptIds + theCells->GetNumberOfConnectivityEntries();
740
741     bool mapBalls = false; 
742     if(theBallArr && theDiamArray) {
743       mapBalls = true;
744     }
745
746     while ( ptIds < endPtIds ) {
747       vtkIdType nPts = *ptIds;
748       ++ptIds;
749
750       while ( nPts > 0 ) {
751         TVertex& aVertex = theVertexArr[ theVertexId ];
752         vtkIdType aPointId = *ptIds;
753
754         TCoordinates* anOffsetPoints = theStartPoints + 3 * aPointId;
755         aVertex.vx = anOffsetPoints[0];
756         aVertex.vy = anOffsetPoints[1];
757         aVertex.vz = anOffsetPoints[2];
758
759         theColorFunctor->get( aVertex, aPointId, theCellId );
760
761         ++theVertexId;
762         ++ptIds; 
763         --nPts; 
764       }
765       
766       if(mapBalls){
767         theBallArr[theCellId] = (TBall)theDiamArray->GetTuple(theCellId)[0]*theBallScale;
768       }
769
770       ++theCellId;
771     }
772   }
773
774   //-----------------------------------------------------------------------------
775   template < class TCoordinates >
776   void DrawCellsPoints( vtkPolyData* theInput,
777                         vtkPoints* thePoints,
778                         TColorFunctorBase* theColorFunctor,
779                         TVertex* theVertexArr,
780                         TBall* theBallArr,
781                         double theBallScale )
782   {
783     vtkIdType aCellId = 0, aVertexId = 0;
784
785     TCoordinates* aStartPoints = (TCoordinates*)thePoints->GetVoidPointer(0);
786     vtkDataArray* aDiams = theInput->GetCellData() ? theInput->GetCellData()->GetScalars() : 0;    
787
788     if ( vtkCellArray* aCellArray = theInput->GetVerts() ) {
789       DrawPoints( aStartPoints, aCellArray, theColorFunctor, theVertexArr, aCellId, aVertexId, theBallArr, aDiams, theBallScale );
790     }
791   
792     if ( vtkCellArray* aCellArray = theInput->GetLines() )
793       DrawPoints( aStartPoints, aCellArray, theColorFunctor, theVertexArr, aCellId, aVertexId, theBallArr, aDiams, theBallScale );
794   
795     if ( vtkCellArray* aCellArray = theInput->GetPolys() )
796       DrawPoints( aStartPoints, aCellArray, theColorFunctor, theVertexArr, aCellId, aVertexId, theBallArr, aDiams, theBallScale );
797   
798     if ( vtkCellArray* aCellArray = theInput->GetStrips() )
799       DrawPoints( aStartPoints, aCellArray, theColorFunctor, theVertexArr, aCellId, aVertexId, theBallArr, aDiams, theBallScale ); 
800   }
801 } // namespace VTK
802
803 #ifndef VTK_OPENGL2
804 //-----------------------------------------------------------------------------
805 int VTKViewer_PolyDataMapper::Draw( vtkRenderer* ren, vtkActor* act )
806 {
807   int noAbort = 1;
808   if( (!this->MarkerEnabled || this->MarkerType == VTK::MT_NONE || !this->ImageData.GetPointer()) && !this->BallEnabled)
809     return MAPPER_SUPERCLASS::Draw( ren, act );
810
811   InternalDraw( ren, act );
812
813   return noAbort;
814 }
815 #else
816 //-----------------------------------------------------------------------------
817 void VTKViewer_PolyDataMapper::RenderPieceDraw( vtkRenderer* ren, vtkActor* act ) {
818   int noAbort = 1;
819   if( (!this->MarkerEnabled || this->MarkerType == VTK::MT_NONE || !this->ImageData.GetPointer()) && !this->BallEnabled) {
820     MAPPER_SUPERCLASS::RenderPieceDraw( ren, act );
821     return;
822   }
823   InternalDraw( ren, act );
824 }
825 #endif
826
827 #ifdef VTK_OPENGL2
828 #include <vtkCamera.h>
829 #include <vtkOpenGLCamera.h>
830 #include <vtkOpenGLActor.h>
831 #endif
832
833 void VTKViewer_PolyDataMapper::InternalDraw(vtkRenderer* ren, vtkActor* act ) {
834   vtkUnsignedCharArray* colors = NULL;
835   vtkPolyData* input  = this->GetInput();
836   vtkPoints* points;
837   int cellScalars = 0;
838   vtkProperty* prop = act->GetProperty();
839
840   points = input->GetPoints();
841
842   if ( this->Colors )
843   {
844     if(!this->BallEnabled) {
845       colors = this->Colors;
846       if ( (this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_DATA ||
847             this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_FIELD_DATA ||
848             !input->GetPointData()->GetScalars() )
849            && this->ScalarMode != VTK_SCALAR_MODE_USE_POINT_FIELD_DATA )
850         cellScalars = 1;
851     }
852   }
853
854   {
855     vtkIdType aTotalConnectivitySize = 0;
856     vtkIdType aNbCells = 0;
857
858     if ( vtkCellArray* aCellArray = input->GetVerts() ) {
859       aTotalConnectivitySize += aCellArray->GetNumberOfConnectivityEntries() - aCellArray->GetNumberOfCells();
860       aNbCells += aCellArray->GetNumberOfCells();
861     }
862
863     if ( vtkCellArray* aCellArray = input->GetLines() ) {
864       aTotalConnectivitySize += aCellArray->GetNumberOfConnectivityEntries() - aCellArray->GetNumberOfCells();
865       aNbCells += aCellArray->GetNumberOfCells();
866     }
867
868     if ( vtkCellArray* aCellArray = input->GetPolys() ) {
869       aTotalConnectivitySize += aCellArray->GetNumberOfConnectivityEntries() - aCellArray->GetNumberOfCells();
870       aNbCells += aCellArray->GetNumberOfCells();
871     }
872
873     if ( vtkCellArray* aCellArray = input->GetStrips() ) {
874       aTotalConnectivitySize += aCellArray->GetNumberOfConnectivityEntries() - aCellArray->GetNumberOfCells();
875       aNbCells += aCellArray->GetNumberOfCells();
876     }
877
878     if ( aTotalConnectivitySize > 0 ) {
879       VTK::TVertex* aVertexArr = new VTK::TVertex[ aTotalConnectivitySize ];
880       
881       TBall* aBallArray = 0;
882
883       if(this->BallEnabled) {
884         aBallArray = new TBall[aNbCells];
885       }
886
887       int* aSize = this->ImageData->GetDimensions();
888
889       int aMode = 0; // to remove
890       {
891         VTK::TColorFunctorBase* aColorFunctor = NULL;
892         if( colors && aMode != 1 ) {
893           if ( cellScalars )
894             aColorFunctor = new VTK::TCellColors2Color( prop, colors );
895           else
896             aColorFunctor = new VTK::TPointColors2Color( prop, colors );
897         } else {
898           aColorFunctor = new VTK::TPropertyColor( prop );
899         }
900         if ( points->GetDataType() == VTK_FLOAT )
901           VTK::DrawCellsPoints< float >( input, points, aColorFunctor, aVertexArr, aBallArray, GetBallScale() );
902         else
903           VTK::DrawCellsPoints< double >( input, points, aColorFunctor, aVertexArr, aBallArray, GetBallScale() );
904
905         delete aColorFunctor;
906       }
907
908       if( this->ExtensionsInitialized == ES_Ok ) {
909 #ifdef VTK_OPENGL2
910         GLint current_program;
911         glGetIntegerv( GL_CURRENT_PROGRAM, &current_program );
912         this->OpenGLHelper.vglUseProgramObjectARB( this->PointProgram );
913
914         vtkOpenGLCamera *cam = (vtkOpenGLCamera *)(ren->GetActiveCamera());
915         vtkMatrix4x4 *wcdc;
916         vtkMatrix4x4 *wcvc;
917         vtkMatrix3x3 *norms;
918         vtkMatrix4x4 *vcdc;
919         cam->GetKeyMatrices(ren,wcvc,norms,vcdc,wcdc);
920         if (!act->GetIsIdentity())
921         {
922           vtkMatrix4x4 *mcwc;
923           vtkMatrix3x3 *anorms;
924           ((vtkOpenGLActor *)act)->GetKeyMatrices( mcwc, anorms );
925           vtkMatrix4x4::Multiply4x4( mcwc, wcdc, this->TempMatrix4 );
926
927           this->OpenGLHelper.SetUniformMatrix( this->myLocations.ModelViewProjection, this->TempMatrix4 );
928         }
929         else
930         {
931                 this->OpenGLHelper.SetUniformMatrix( this->myLocations.ModelViewProjection, wcdc );
932         }
933         this->OpenGLHelper.SetUniformMatrix( this->myLocations.Projection, vcdc );
934
935         this->OpenGLHelper.vglUniform1iARB( this->myLocations.GeneralPointSize, std::max( aSize[0], aSize[1] ) );
936
937         GLuint aBufferObjectID, aDiamsID = 0;
938
939         this->OpenGLHelper.vglBindVertexArrayARB( this->VertexArrayObject );
940         this->OpenGLHelper.vglGenBuffersARB( 1, &aBufferObjectID );
941         this->OpenGLHelper.vglBindBufferARB( GL_ARRAY_BUFFER_ARB, aBufferObjectID );
942         
943         int anArrayObjectSize = sizeof( VTK::TVertex ) * aTotalConnectivitySize;
944         this->OpenGLHelper.vglBufferDataARB( GL_ARRAY_BUFFER_ARB, anArrayObjectSize, aVertexArr, GL_STATIC_DRAW_ARB );
945         
946         delete [] aVertexArr;
947         
948
949         GLint colorAttrib  = this->OpenGLHelper.vglGetAttribLocationARB( this->PointProgram, "Color" );
950         GLint vertexAttrib = this->OpenGLHelper.vglGetAttribLocationARB( this->PointProgram, "Vertex" );
951         GLint diamAttrib   = this->OpenGLHelper.vglGetAttribLocationARB( this->PointProgram, "Diameter" );
952
953         GLsizei vertexSize = sizeof(VTK::TVertex);
954
955         this->OpenGLHelper.vglVertexAttribPointerARB( colorAttrib, 4, GL_FLOAT, GL_FALSE, vertexSize, (const GLvoid*)0 );
956         this->OpenGLHelper.vglEnableVertexAttribArrayARB( colorAttrib );
957
958         this->OpenGLHelper.vglVertexAttribPointerARB( vertexAttrib, 3, GL_FLOAT, GL_FALSE, vertexSize, (const GLvoid*)(sizeof(GLfloat) * 4) );
959         this->OpenGLHelper.vglEnableVertexAttribArrayARB( vertexAttrib );
960
961        if(this->BallEnabled) {
962          // Don't use uniform variable.
963          this->OpenGLHelper.vglUniform1iARB( this->myLocations.GeneralPointSize, -1 );
964          this->OpenGLHelper.vglGenBuffersARB( 1, &aDiamsID);
965          this->OpenGLHelper.vglBindBufferARB( GL_ARRAY_BUFFER_ARB, aDiamsID);
966
967          int aDiamsSize = sizeof(TBall)*aNbCells;
968          this->OpenGLHelper.vglBufferDataARB( GL_ARRAY_BUFFER_ARB, aDiamsSize, aBallArray, GL_STATIC_DRAW_ARB);
969
970          delete [] aBallArray;
971
972          this->OpenGLHelper.vglVertexAttribPointerARB( diamAttrib, 1, GL_FLOAT, GL_FALSE, 0, 0 );
973          this->OpenGLHelper.vglEnableVertexAttribArrayARB( diamAttrib );
974        }
975
976        glDrawArrays( GL_POINTS, 0, aTotalConnectivitySize );
977
978        if( this->BallEnabled ) {
979          this->OpenGLHelper.vglDisableVertexAttribArrayARB( diamAttrib );
980          this->OpenGLHelper.vglBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 );
981          this->OpenGLHelper.vglDeleteBuffersARB( 1, &aDiamsID );
982        }
983
984        this->OpenGLHelper.vglDisableVertexAttribArrayARB( colorAttrib );
985        this->OpenGLHelper.vglDisableVertexAttribArrayARB( vertexAttrib );
986        this->OpenGLHelper.vglBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 );
987        this->OpenGLHelper.vglDeleteBuffersARB( 1, &aBufferObjectID );
988        this->OpenGLHelper.vglBindVertexArrayARB( 0 );
989
990        this->OpenGLHelper.vglUseProgramObjectARB( current_program );
991 #else
992        GLuint aBufferObjectID, aDiamsID = 0;
993        GLint attribute_diams = -1;
994        glPointSize( std::max( aSize[0], aSize[1] ) );
995        this->OpenGLHelper.vglGenBuffersARB( 1, &aBufferObjectID );
996        this->OpenGLHelper.vglBindBufferARB( GL_ARRAY_BUFFER_ARB, aBufferObjectID );
997
998        int anArrayObjectSize = sizeof( VTK::TVertex ) * aTotalConnectivitySize;
999        this->OpenGLHelper.vglBufferDataARB( GL_ARRAY_BUFFER_ARB, anArrayObjectSize, aVertexArr, GL_STATIC_DRAW_ARB );
1000
1001        delete [] aVertexArr;
1002
1003        this->OpenGLHelper.vglBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 );
1004        this->OpenGLHelper.vglBindBufferARB( GL_ARRAY_BUFFER_ARB, aBufferObjectID );
1005         
1006         glColorPointer( 4, GL_FLOAT, sizeof(VTK::TVertex), (void*)0 );
1007         glVertexPointer( 3, GL_FLOAT, sizeof(VTK::TVertex), (void*)(4*sizeof(GLfloat)) );
1008         
1009         glEnableClientState( GL_VERTEX_ARRAY );
1010         glEnableClientState( GL_COLOR_ARRAY );
1011
1012         if(this->BallEnabled) {
1013                 this->OpenGLHelper.vglGenBuffersARB( 1, &aDiamsID);
1014                 this->OpenGLHelper.vglBindBufferARB( GL_ARRAY_BUFFER_ARB, aDiamsID);
1015
1016           int aDiamsSize = sizeof(TBall)*aNbCells;
1017           this->OpenGLHelper.vglBufferDataARB( GL_ARRAY_BUFFER_ARB, aDiamsSize, aBallArray, GL_STATIC_DRAW_ARB);
1018
1019           delete [] aBallArray;
1020           this->OpenGLHelper.vglBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 );
1021           this->OpenGLHelper.vglBindBufferARB( GL_ARRAY_BUFFER_ARB, aDiamsID );
1022
1023           attribute_diams = this->OpenGLHelper.vglGetAttribLocationARB(this->PointProgram, "diameter");
1024           this->OpenGLHelper.vglEnableVertexAttribArrayARB(attribute_diams);
1025           this->OpenGLHelper.vglBindBufferARB(GL_ARRAY_BUFFER_ARB, aDiamsID);
1026           this->OpenGLHelper.vglVertexAttribPointerARB(
1027                                     attribute_diams,   // attribute
1028                                     1,                 // number of elements per vertex, here (diameter)
1029                                     GL_FLOAT,          // the type of each element
1030                                     GL_FALSE,          // take our values as-is
1031                                     0,                 // no extra data between each position
1032                                     0                  // offset of first element
1033                                     );
1034         }
1035
1036         glDrawArrays( GL_POINTS, 0, aTotalConnectivitySize );
1037         
1038         glDisableClientState( GL_COLOR_ARRAY );
1039         glDisableClientState( GL_VERTEX_ARRAY );       
1040         this->OpenGLHelper.vglDeleteBuffersARB( 1, &aBufferObjectID );
1041
1042         if(this->BallEnabled) {
1043                 this->OpenGLHelper.vglDisableVertexAttribArrayARB(attribute_diams);
1044                 this->OpenGLHelper.vglDeleteBuffersARB( 1, &aDiamsID );
1045         }
1046
1047 #endif
1048           } else { // there are no extensions
1049         glColorPointer( 4, GL_FLOAT, sizeof(VTK::TVertex), aVertexArr );
1050         glVertexPointer( 3, GL_FLOAT, sizeof(VTK::TVertex), 
1051                          (void*)((GLfloat*)((void*)(aVertexArr)) + 4));
1052
1053         glEnableClientState( GL_VERTEX_ARRAY );
1054         glEnableClientState( GL_COLOR_ARRAY );
1055         
1056         glDrawArrays( GL_POINTS, 0, aTotalConnectivitySize );
1057         
1058         glDisableClientState( GL_COLOR_ARRAY );
1059         glDisableClientState( GL_VERTEX_ARRAY );
1060
1061         delete [] aVertexArr;
1062       }
1063     }
1064   }
1065
1066   this->UpdateProgress(1.0);
1067 }