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