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