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