Salome HOME
Fix for Bug IPAL8945
[modules/visu.git] / src / PIPELINE / VISU_OpenGLPointSpriteMapper.cxx
1 //  VISU OBJECT : interactive object for VISU entities implementation
2 //
3 //  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 //  This library is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU Lesser General Public
8 //  License as published by the Free Software Foundation; either
9 //  version 2.1 of the License.
10 //
11 //  This library is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 //  Lesser General Public License for more details.
15 //
16 //  You should have received a copy of the GNU Lesser General Public
17 //  License along with this library; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 //  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
21 //
22 //
23 //
24 // File:    VISU_OpenGLPointSpriteMapper.cxx
25 // Author:  
26 // Module : VISU
27
28 #include "VISU_OpenGLPointSpriteMapper.hxx"
29
30 #include <vtkCamera.h>
31 #include <vtkCellArray.h>
32 #include <vtkCellData.h>
33 #include <vtkCommand.h>
34 #include <vtkDataArray.h>
35 #include <vtkFloatArray.h>
36 #include <vtkImageData.h>
37 #include <vtkMatrix4x4.h>
38 #include <vtkObjectFactory.h>
39 #include <vtkOpenGLRenderer.h>
40 #include <vtkOpenGLRenderWindow.h>
41 #include <vtkPointData.h>
42 #include <vtkPolyData.h>
43 #include <vtkPolygon.h>
44 #include <vtkProperty.h>
45 #include <vtkTimerLog.h>
46 #include <vtkTriangle.h>
47
48 #include <dlfcn.h>
49
50 #include <stdio.h>
51 #include <cmath>
52 #include <string>
53
54 #ifndef VTK_IMPLEMENT_MESA_CXX
55 vtkCxxRevisionMacro(VISU_OpenGLPointSpriteMapper, "Revision$");
56 vtkStandardNewMacro(VISU_OpenGLPointSpriteMapper);
57 #endif
58
59 // some definitions for what the polydata has in it
60 #define VTK_PDPSM_COLORS             0x0001
61 #define VTK_PDPSM_CELL_COLORS        0x0002
62 #define VTK_PDPSM_POINT_TYPE_FLOAT   0x0004
63 #define VTK_PDPSM_POINT_TYPE_DOUBLE  0x0008
64 #define VTK_PDPSM_NORMAL_TYPE_FLOAT  0x0010
65 #define VTK_PDPSM_NORMAL_TYPE_DOUBLE 0x0020
66 #define VTK_PDPSM_OPAQUE_COLORS      0x0040
67
68 #ifndef APIENTRY
69 #define APIENTRY
70 #endif
71 #ifndef APIENTRYP
72 #define APIENTRYP APIENTRY *
73 #endif
74
75 #ifndef GL_OBJECT_INFO_LOG_LENGTH_ARB
76 #define GL_OBJECT_INFO_LOG_LENGTH_ARB     0x8B84
77 #endif
78
79 #ifndef GL_VERTEX_SHADER_ARB
80 #define GL_VERTEX_SHADER_ARB              0x8B31
81 #endif
82
83 #ifndef GL_VERTEX_PROGRAM_POINT_SIZE_ARB
84 #define GL_VERTEX_PROGRAM_POINT_SIZE_ARB  0x8642
85 #endif
86
87 #ifndef GL_ARB_point_sprite
88 #define GL_POINT_SPRITE_ARB               0x8861
89 #define GL_COORD_REPLACE_ARB              0x8862
90 #endif
91
92 #ifndef GL_ARB_shader_objects
93 typedef char GLcharARB;
94 #endif
95
96 #ifndef GL_ARB_vertex_buffer_object
97 typedef ptrdiff_t GLsizeiptrARB;
98
99 #define GL_ARRAY_BUFFER_ARB               0x8892
100 #define GL_STATIC_DRAW_ARB                0x88E4
101 #endif
102
103 typedef void (APIENTRYP PFNGLSHADERSOURCEARBPROC) (GLhandleARB shaderObj, GLsizei count, const GLcharARB* *string, const GLint *length);
104 typedef GLhandleARB (APIENTRYP PFNGLCREATESHADEROBJECTARBPROC) (GLenum shaderType);
105 typedef void (APIENTRYP PFNGLCOMPILESHADERARBPROC) (GLhandleARB shaderObj);
106 typedef GLhandleARB (APIENTRYP PFNGLCREATEPROGRAMOBJECTARBPROC) (void);
107 typedef void (APIENTRYP PFNGLATTACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB obj);
108 typedef void (APIENTRYP PFNGLLINKPROGRAMARBPROC) (GLhandleARB programObj);
109 typedef void (APIENTRYP PFNGLUSEPROGRAMOBJECTARBPROC) (GLhandleARB programObj);
110 typedef void (APIENTRYP PFNGLGETOBJECTPARAMETERIVARBPROC) (GLhandleARB obj, GLenum pname, GLint *params);
111 typedef void (APIENTRYP PFNGLGETINFOLOGARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *infoLog);
112 typedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB *name);
113 typedef void (APIENTRYP PFNGLVERTEXATTRIB1FARBPROC) (GLuint index, GLfloat x);
114
115 typedef void (APIENTRYP PFNGLBINDBUFFERARBPROC) (GLenum target, GLuint buffer);
116 typedef void (APIENTRYP PFNGLDELETEBUFFERSARBPROC) (GLsizei n, const GLuint *buffers);
117 typedef void (APIENTRYP PFNGLGENBUFFERSARBPROC) (GLsizei n, GLuint *buffers);
118 typedef void (APIENTRYP PFNGLBUFFERDATAARBPROC) (GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage);
119
120 static PFNGLSHADERSOURCEARBPROC             vglShaderSourceARB            = NULL;
121 static PFNGLCREATESHADEROBJECTARBPROC       vglCreateShaderObjectARB      = NULL;
122 static PFNGLCOMPILESHADERARBPROC            vglCompileShaderARB           = NULL;
123 static PFNGLCREATEPROGRAMOBJECTARBPROC      vglCreateProgramObjectARB     = NULL;
124 static PFNGLATTACHOBJECTARBPROC             vglAttachObjectARB            = NULL;
125 static PFNGLLINKPROGRAMARBPROC              vglLinkProgramARB             = NULL;
126 static PFNGLUSEPROGRAMOBJECTARBPROC         vglUseProgramObjectARB        = NULL;
127 static PFNGLGETOBJECTPARAMETERIVARBPROC     vglGetObjectParameterivARB    = NULL;
128 static PFNGLGETINFOLOGARBPROC               vglGetInfoLogARB              = NULL;
129 static PFNGLGETATTRIBLOCATIONARBPROC        vglGetAttribLocationARB       = NULL;
130 static PFNGLVERTEXATTRIB1FARBPROC           vglVertexAttrib1fARB          = NULL;
131
132 static PFNGLGENBUFFERSARBPROC               vglGenBuffersARB              = NULL;
133 static PFNGLBINDBUFFERARBPROC               vglBindBufferARB              = NULL;
134 static PFNGLBUFFERDATAARBPROC               vglBufferDataARB              = NULL;
135 static PFNGLDELETEBUFFERSARBPROC            vglDeleteBuffersARB           = NULL;
136
137 int InitializeARB()
138 {
139   void* OpenGLLibrary = dlopen( "libGL.so", RTLD_LAZY );
140
141   vglShaderSourceARB = (PFNGLSHADERSOURCEARBPROC)dlsym( OpenGLLibrary, "glShaderSourceARB" );
142   vglCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC)dlsym( OpenGLLibrary, "glCreateShaderObjectARB" );
143   vglCompileShaderARB = (PFNGLCOMPILESHADERARBPROC)dlsym( OpenGLLibrary, "glCompileShaderARB" );
144   vglCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC)dlsym( OpenGLLibrary, "glCreateProgramObjectARB" );
145   vglAttachObjectARB = (PFNGLATTACHOBJECTARBPROC)dlsym( OpenGLLibrary, "glAttachObjectARB" );
146   vglLinkProgramARB = (PFNGLLINKPROGRAMARBPROC)dlsym( OpenGLLibrary, "glLinkProgramARB" );
147   vglUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC)dlsym( OpenGLLibrary, "glUseProgramObjectARB" );
148   vglGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC)dlsym( OpenGLLibrary, "glGetObjectParameterivARB" );
149   vglGetInfoLogARB = (PFNGLGETINFOLOGARBPROC)dlsym( OpenGLLibrary, "glGetInfoLogARB" );
150   vglGetAttribLocationARB = (PFNGLGETATTRIBLOCATIONARBPROC)dlsym( OpenGLLibrary, "glGetAttribLocationARB" );
151   vglVertexAttrib1fARB = (PFNGLVERTEXATTRIB1FARBPROC)dlsym( OpenGLLibrary, "glVertexAttrib1fARB" );
152
153   vglGenBuffersARB = (PFNGLGENBUFFERSARBPROC)dlsym( OpenGLLibrary, "glGenBuffersARB" );
154   vglBindBufferARB = (PFNGLBINDBUFFERARBPROC)dlsym( OpenGLLibrary, "glBindBufferARB" );
155   vglBufferDataARB = (PFNGLBUFFERDATAARBPROC)dlsym( OpenGLLibrary, "glBufferDataARB" );
156   vglDeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC)dlsym( OpenGLLibrary, "glDeleteBuffersARB" );
157
158   return 1;
159 };
160
161 static int IsARBInitialized = InitializeARB();
162 static float Tolerance = 1.0 / VTK_LARGE_FLOAT;
163
164 //-----------------------------------------------------------------------------
165 // Construct empty object.
166 VISU_OpenGLPointSpriteMapper::VISU_OpenGLPointSpriteMapper()
167 {
168   this->RenderMode               = VISU_OpenGLPointSpriteMapper::Occlude;
169
170   this->ListId                   = 0;
171   this->TotalCells               = 0;
172   this->ExtensionsInitialized    = 0;
173   this->DefaultPointSize         = 20.0;
174   this->AverageCellSize          = 0.0;
175
176   this->UsePointSprites          = true;
177   this->UseTextures              = true;
178   this->UseShader                = true;
179
180   this->PrimitiveType            = VISU_OpenGLPointSpriteMapper::PointSprite;
181
182   this->PointSpriteMode          = 0;
183
184   this->PointSpriteClamp         = 256.0;
185   this->PointSpriteSize          = 0.2;
186   this->PointSpriteMinSize       = 0.1;
187   this->PointSpriteMaxSize       = 0.3;
188   this->PointSpriteMagnification = 1.0;
189
190   this->PointSpriteAlphaThreshold = 0.5;
191   this->PointSpriteTexture       = 0;
192
193   this->UseOpenGLMapper          = false;
194
195   this->TempMapper               = vtkPolyDataMapper::New();
196 }
197 //-----------------------------------------------------------------------------
198 VISU_OpenGLPointSpriteMapper::~VISU_OpenGLPointSpriteMapper()
199 {
200   glDeleteTextures( 1, &PointSpriteTexture );
201
202   if( this->LastWindow )
203     this->ReleaseGraphicsResources(this->LastWindow);
204
205   if( this->TempMapper )
206     this->TempMapper->Delete();
207 }
208 //-----------------------------------------------------------------------------
209 void VISU_OpenGLPointSpriteMapper::ShallowCopy( vtkAbstractMapper* mapper )
210 {
211   VISU_OpenGLPointSpriteMapper* m = VISU_OpenGLPointSpriteMapper::SafeDownCast(mapper);
212   if( m != NULL )
213   {
214     this->SetPrimitiveType( m->GetPrimitiveType() );
215
216     this->SetPointSpriteMode( m->GetPointSpriteMode() );
217
218     this->SetPointSpriteClamp( m->GetPointSpriteClamp() );
219     this->SetPointSpriteSize( m->GetPointSpriteSize() );
220     this->SetPointSpriteMinSize( m->GetPointSpriteMinSize() );
221     this->SetPointSpriteMaxSize( m->GetPointSpriteMaxSize() );
222     this->SetPointSpriteMagnification( m->GetPointSpriteMagnification() );
223
224     this->SetImageData( m->GetImageData() );
225     this->SetPointSpriteAlphaThreshold( m->GetPointSpriteAlphaThreshold() );
226   }
227
228   this->TempMapper->ShallowCopy( m );
229   this->TempMapper->SetInput( this->GetInput() );
230   Superclass::ShallowCopy( this->TempMapper );
231
232 }
233 //-----------------------------------------------------------------------------
234 char* readFromFile( std::string fileName )
235 {
236   FILE* file = fopen( fileName.c_str(), "r" );
237
238   char* content = NULL;
239   int count = 0;
240
241   if( file != NULL )
242   {
243     fseek( file, 0, SEEK_END );
244     count = ftell( file );
245     rewind( file );
246
247     if( count > 0 )
248     {
249       content = ( char* )malloc( sizeof( char ) * ( count + 1 ) );
250       count = fread( content, sizeof( char ), count, file );
251       content[ count ] = '\0';
252     }
253     fclose( file );
254   }
255
256   return content;
257 }
258 //-----------------------------------------------------------------------------
259 void VISU_OpenGLPointSpriteMapper::PrintInfoLog( GLhandleARB obj )
260 {
261   int infologLength = 0;
262   int charsWritten  = 0;
263   char* infoLog;
264
265   vglGetObjectParameterivARB( obj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &infologLength );
266
267   if( infologLength > 0 )
268   {
269     infoLog = ( char* )malloc( infologLength );
270     vglGetInfoLogARB( obj, infologLength, &charsWritten, infoLog );
271     printf( "%s\n", infoLog );
272     free( infoLog );
273   }
274 }
275 //-----------------------------------------------------------------------------
276 void VISU_OpenGLPointSpriteMapper::InitShader()
277 {
278   //cout << "Initializing vertex program" << endl;
279
280   std::string fileName = std::string( getenv( "VISU_ROOT_DIR") ) +
281                          "/share/salome/resources/Vertex_Program_ARB.txt";
282
283   char* shader = readFromFile( fileName );
284
285   GLhandleARB VertexShader = vglCreateShaderObjectARB( GL_VERTEX_SHADER_ARB );
286   vglShaderSourceARB( VertexShader, 1, (const GLcharARB**)&shader, NULL );
287   vglCompileShaderARB( VertexShader );
288   //this->PrintInfoLog( VertexShader );
289
290   this->VertexProgram = vglCreateProgramObjectARB();
291   vglAttachObjectARB( this->VertexProgram, VertexShader );
292
293   vglLinkProgramARB( this->VertexProgram );
294   //this->PrintInfoLog( VertexProgram );
295   /*
296   cout << "Shader from " << fileName << endl;
297   for( int i = 0; i < strlen( shader ); i++ )
298     cout << shader[i];
299   cout << endl;
300
301   if( glGetError() == GL_NO_ERROR )
302     cout << "Loading vertex program... ok" << endl << endl;
303   else
304     cout << "Loading vertex program... failed" << endl << endl;
305   */
306   free( shader );
307 }
308 //-----------------------------------------------------------------------------
309 void VISU_OpenGLPointSpriteMapper::SetShaderVariable( const char* variable, float value )
310 {
311   //cout << this->VertexProgram << " ";
312   //cout << vglGetAttribLocationARB( this->VertexProgram, variable ) << " ";
313   //cout << variable << " " << value << endl;
314
315   vglVertexAttrib1fARB( vglGetAttribLocationARB( this->VertexProgram, variable ), value );
316 }
317 //-----------------------------------------------------------------------------
318 void VISU_OpenGLPointSpriteMapper::SetPrimitiveType( int thePrimitiveType )
319 {
320   if( this->PrimitiveType == thePrimitiveType )
321     return;
322
323   this->PrimitiveType = thePrimitiveType;
324 }
325 //-----------------------------------------------------------------------------
326 void VISU_OpenGLPointSpriteMapper::SetPointSpriteMode( int theMode )
327 {
328   if( this->PointSpriteMode == theMode )
329     return;
330
331   this->PointSpriteMode = theMode;
332   this->Modified();
333 }
334 //-----------------------------------------------------------------------------
335 void VISU_OpenGLPointSpriteMapper::SetPointSpriteClamp( float theClamp )
336 {
337   if( fabs( this->PointSpriteClamp - theClamp ) < Tolerance )
338     return;
339
340   this->PointSpriteClamp = theClamp;
341 }
342 //-----------------------------------------------------------------------------
343 void VISU_OpenGLPointSpriteMapper::SetPointSpriteSize( float theSize )
344 {
345   if( fabs( this->PointSpriteSize - theSize ) < Tolerance )
346     return;
347
348   this->PointSpriteSize = theSize;
349 }
350 //-----------------------------------------------------------------------------
351 void VISU_OpenGLPointSpriteMapper::SetPointSpriteMinSize( float theMinSize )
352 {
353   if( fabs( this->PointSpriteMinSize - theMinSize ) < Tolerance )
354     return;
355
356   this->PointSpriteMinSize = theMinSize;
357 }
358 //-----------------------------------------------------------------------------
359 void VISU_OpenGLPointSpriteMapper::SetPointSpriteMaxSize( float theMaxSize )
360 {
361   if( fabs( this->PointSpriteMaxSize - theMaxSize ) < Tolerance )
362     return;
363
364   this->PointSpriteMaxSize = theMaxSize;
365 }
366 //-----------------------------------------------------------------------------
367 void VISU_OpenGLPointSpriteMapper::SetPointSpriteMagnification( float theMagnification )
368 {
369   if( fabs( this->PointSpriteMagnification - theMagnification ) < Tolerance )
370     return;
371
372   this->PointSpriteMagnification = theMagnification;
373 }
374 //-----------------------------------------------------------------------------
375 void VISU_OpenGLPointSpriteMapper::SetPointSpriteAlphaThreshold( float theAlphaThreshold )
376 {
377   if( fabs( this->PointSpriteAlphaThreshold - theAlphaThreshold ) < Tolerance )
378     return;
379
380   this->PointSpriteAlphaThreshold = theAlphaThreshold;
381 }
382 //-----------------------------------------------------------------------------
383 bool VISU_OpenGLPointSpriteMapper::InitExtensions()
384 {
385   char* ext = (char*)glGetString( GL_EXTENSIONS );
386   //cout << "OpenGL extensions : " << ext << endl;
387
388   if( strstr( ext, "GL_ARB_point_sprite" ) == NULL ||
389       strstr( ext, "GL_ARB_shader_objects" ) == NULL ||
390       strstr( ext, "GL_ARB_vertex_buffer_object" ) == NULL )
391   {
392     vtkWarningMacro(<<"Initializing ARB extensions failed");
393
394     this->UseOpenGLMapper = true;
395
396     return false;
397   }
398
399   if( this->UseShader )
400     this->InitShader();
401
402   this->ExtensionsInitialized = 1;
403   return true;
404 }
405
406 //-----------------------------------------------------------------------------
407 float ViewToDisplay( vtkRenderer* theRenderer )
408 {
409   float p1[3], p2[3];
410
411   theRenderer->SetViewPoint( 0.0, 0.0, 0.0 );
412   theRenderer->ViewToDisplay();
413   theRenderer->GetDisplayPoint( p1 );
414
415   theRenderer->SetViewPoint( 1.0, 1.0, 1.0 );
416   theRenderer->ViewToDisplay();
417   theRenderer->GetDisplayPoint( p2 );
418
419   float coefficient = sqrt( pow( p2[0] - p1[0], 2 ) + pow( p2[1] - p1[1], 2 ) ) / sqrt( 2 );
420   //cout << p1[0] << " " << p1[1] << " " << p1[2] << endl;
421   //cout << p2[0] << " " << p2[1] << " " << p2[2] << endl;
422   //cout << "ZOOM  : " << coefficient << endl;
423
424   return coefficient;
425 }
426
427 //-----------------------------------------------------------------------------
428 //
429 // Receives from Actor -> maps data to primitives
430 //
431 void VISU_OpenGLPointSpriteMapper::RenderPiece(vtkRenderer *ren, vtkActor *act)
432 {
433   bool isUseThisMapper = !( this->UseOpenGLMapper ||
434                             this->PrimitiveType == VISU_OpenGLPointSpriteMapper::GeomSphere );
435
436   if( !this->ExtensionsInitialized && isUseThisMapper )
437   {
438     if( !this->InitExtensions() )
439       return;
440   }
441
442   if( !isUseThisMapper )
443   {
444     MAPPER_SUPERCLASS::RenderPiece( ren, act );
445     return;
446   }
447
448   vtkIdType numPts;
449   vtkPolyData *input= this->GetInput();
450
451   //
452   // make sure that we've been properly initialized
453   //
454   if (ren->GetRenderWindow()->CheckAbortStatus())
455     return;
456
457   if ( input == NULL )
458   {
459     vtkErrorMacro(<< "No input!");
460     return;
461   }
462   else
463   {
464     this->InvokeEvent(vtkCommand::StartEvent,NULL);
465     input->Update();
466     this->InvokeEvent(vtkCommand::EndEvent,NULL);
467
468     numPts = input->GetNumberOfPoints();
469   }
470
471   if (numPts == 0)
472   {
473     vtkDebugMacro(<< "No points!");
474     return;
475   }
476
477   if ( this->LookupTable == NULL )
478     this->CreateDefaultLookupTable();
479
480   // make sure our window is current
481   ren->GetRenderWindow()->MakeCurrent();
482
483   if( this->UsePointSprites ) //&& this->PrimitiveType == VISU_OpenGLPointSpriteMapper::PointSprite )
484     this->InitPointSprites();
485
486   // Initializing the texture for Point Sprites
487   if( this->UseTextures && this->PrimitiveType == VISU_OpenGLPointSpriteMapper::PointSprite )
488     this->InitTextures();
489
490   vglUseProgramObjectARB( this->VertexProgram );
491   float aViewToDisplay = ViewToDisplay( ren );
492   this->SetShaderVariable( "mode",          this->PointSpriteMode );
493   this->SetShaderVariable( "clampSize",     this->PointSpriteClamp );
494   this->SetShaderVariable( "geomSize",      aViewToDisplay * this->AverageCellSize * this->PointSpriteSize );
495   this->SetShaderVariable( "minSize",       aViewToDisplay * this->AverageCellSize * this->PointSpriteMinSize );
496   this->SetShaderVariable( "maxSize",       aViewToDisplay * this->AverageCellSize * this->PointSpriteMaxSize );
497   this->SetShaderVariable( "magnification", this->PointSpriteMagnification );
498
499   //
500   // if something has changed regenerate colors and display lists
501   // if required
502   //
503   int noAbort=1;
504   if ( this->GetMTime() > this->BuildTime ||
505        input->GetMTime() > this->BuildTime ||
506        act->GetProperty()->GetMTime() > this->BuildTime ||
507        ren->GetRenderWindow() != this->LastWindow)
508   {
509     // sets this->Colors as side effect
510     this->MapScalars( act->GetProperty()->GetOpacity() );
511
512     if (!this->ImmediateModeRendering &&
513         !this->GetGlobalImmediateModeRendering())
514     {
515       this->ReleaseGraphicsResources(ren->GetRenderWindow());
516       this->LastWindow = ren->GetRenderWindow();
517
518       // get a unique display list id
519       this->ListId = glGenLists(1);
520       glNewList(this->ListId,GL_COMPILE);
521
522       noAbort = this->Draw(ren,act);
523       glEndList();
524
525       // Time the actual drawing
526       this->Timer->StartTimer();
527       glCallList(this->ListId);
528       this->Timer->StopTimer();
529     }
530     else
531     {
532       this->ReleaseGraphicsResources(ren->GetRenderWindow());
533       this->LastWindow = ren->GetRenderWindow();
534     }
535     if (noAbort)
536       this->BuildTime.Modified();
537   }
538   // if nothing changed but we are using display lists, draw it
539   else
540   {
541     if (!this->ImmediateModeRendering &&
542         !this->GetGlobalImmediateModeRendering())
543     {
544       // Time the actual drawing
545       this->Timer->StartTimer();
546       glCallList(this->ListId);
547       this->Timer->StopTimer();
548     }
549   }
550
551   // if we are in immediate mode rendering we always
552   // want to draw the primitives here
553   if (this->ImmediateModeRendering ||
554       this->GetGlobalImmediateModeRendering())
555   {
556     // sets this->Colors as side effect
557     this->MapScalars( act->GetProperty()->GetOpacity() );
558
559     // Time the actual drawing
560     this->Timer->StartTimer();
561     this->Draw(ren,act);
562     this->Timer->StopTimer();
563   }
564
565   this->TimeToDraw = (float)this->Timer->GetElapsedTime();
566
567   // If the timer is not accurate enough, set it to a small
568   // time so that it is not zero
569   if ( this->TimeToDraw == 0.0 )
570     this->TimeToDraw = 0.0001;
571
572   vglUseProgramObjectARB( 0 );
573
574   if( this->UsePointSprites ) //&& this->PrimitiveType == VISU_OpenGLPointSpriteMapper::PointSprite )
575     this->CleanupPointSprites();
576 }
577 //-----------------------------------------------------------------------------
578 float VISU_OpenGLPointSpriteMapper::GetMaximumSupportedSize()
579 {
580   float maximumSupportedSize = 512.0;
581   //glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maximumSupportedSize );
582
583   return maximumSupportedSize;
584 }
585 //-----------------------------------------------------------------------------
586 void VISU_OpenGLPointSpriteMapper::InitPointSprites()
587 {
588   glEnable( GL_POINT_SPRITE_ARB );
589   glEnable( GL_VERTEX_PROGRAM_POINT_SIZE_ARB );
590
591   switch (this->RenderMode)
592   {
593     case VISU_OpenGLPointSpriteMapper::Accumulate:
594     {
595       glDisable(GL_DEPTH_TEST);
596
597       glEnable( GL_BLEND );
598       glBlendFunc( GL_SRC_ALPHA, GL_ONE );
599
600       glEnable( GL_ALPHA_TEST );
601       glAlphaFunc( GL_GREATER, this->PointSpriteAlphaThreshold );
602       break;
603     }
604
605     case VISU_OpenGLPointSpriteMapper::Occlude:
606     {
607       glDepthFunc( GL_LEQUAL );
608       glEnable( GL_DEPTH_TEST );
609
610       glEnable( GL_ALPHA_TEST );
611       glAlphaFunc( GL_GREATER, this->PointSpriteAlphaThreshold );
612
613       glDisable( GL_BLEND );
614       break;
615     }
616
617     default:
618     {
619       break;
620     }
621   }
622   // Disable Lighting/Shading.
623   glDisable( GL_LIGHTING );
624
625   // Disable material properties
626   glDisable( GL_COLOR_MATERIAL );
627 }
628 //-----------------------------------------------------------------------------
629 void VISU_OpenGLPointSpriteMapper::CleanupPointSprites()
630 {
631   // Set GL params back to normal to stop other vtkMappers displaying wrongly
632   glDisable( GL_ALPHA_TEST );
633
634   glEnable( GL_BLEND );
635
636   glEnable( GL_DEPTH_TEST );
637   glEnable( GL_LIGHTING );
638   glEnable( GL_COLOR_MATERIAL );
639
640   glDisable( GL_VERTEX_PROGRAM_POINT_SIZE_ARB );
641   glDisable( GL_POINT_SPRITE_ARB );
642 }
643
644
645 //-----------------------------------------------------------------------------
646 void
647 VISU_OpenGLPointSpriteMapper
648 ::SetImageData( vtkImageData* theImageData )
649 {
650   //cout << "VISU_OpenGLPointSpriteMapper::SetImageData " << theImageData << endl;
651   this->ImageData = theImageData;
652 }
653
654 vtkImageData*
655 VISU_OpenGLPointSpriteMapper
656 ::GetImageData()
657 {
658   return this->ImageData.GetPointer();
659 }
660
661
662 //-----------------------------------------------------------------------------
663 void VISU_OpenGLPointSpriteMapper::InitTextures()
664 {
665   //cout << "VISU_OpenGLPointSpriteMapper::InitTextures " << this->GetImageData() << endl;
666   if( !this->GetImageData() )
667     return;
668
669   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
670   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
671   glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
672   glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
673
674   int* aSize = GetImageData()->GetDimensions();
675   unsigned char* dataPtr = (unsigned char*)GetImageData()->GetScalarPointer();
676   glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, aSize[0], aSize[1], 0,
677                 GL_RGBA, GL_UNSIGNED_BYTE, dataPtr );
678
679   //glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
680   glEnable( GL_TEXTURE_2D );
681   glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE );
682   glBindTexture( GL_TEXTURE_2D, this->PointSpriteTexture );
683 }
684
685 //-----------------------------------------------------------------------------
686 int ComputeHue( int r, int g, int b )
687 {
688   int h = 0;
689
690   int max = r;
691   int whatmax = 0;
692   if( g > max ) {
693     max = g;
694     whatmax = 1;
695   }
696   if( b > max ) {
697     max = b;
698     whatmax = 2;
699   }
700
701   int min = r;
702   if ( g < min ) min = g;
703   if ( b < min ) min = b;
704   int delta = max-min;
705
706   if( delta == 0 )
707     h = 0;
708   else if( whatmax == 0 ) {
709     if ( g >= b )
710       h = (120*(g-b)+delta)/(2*delta);
711     else
712       h = (120*(g-b+delta)+delta)/(2*delta) + 300;
713   }
714   else if( whatmax == 1 ) {
715     if ( b > r )
716       h = 120 + (120*(b-r)+delta)/(2*delta);
717     else
718       h = 60 + (120*(b-r+delta)+delta)/(2*delta);
719   }
720   else {
721     if ( r > g )
722       h = 240 + (120*(r-g)+delta)/(2*delta);
723     else
724       h = 180 + (120*(r-g+delta)+delta)/(2*delta);
725   }
726
727   return h + 1;
728 }
729
730 //-----------------------------------------------------------------------------
731 struct TVertex
732 {
733   GLfloat r, g, b, hue;
734   GLfloat vx, vy, vz;
735 };
736
737 //-----------------------------------------------------------------------------
738 void VISU_OpenGLPointSpriteMapper::DrawPoints(vtkPoints *thePoints,
739                                               vtkUnsignedCharArray *theColors,
740                                               vtkFloatArray *theAlpha,
741                                               vtkIdType &theCellNum,
742                                               int &theNoAbort,
743                                               vtkCellArray *theCells,
744                                               vtkRenderer *theRenderer,
745                                               vtkActor* theActor)
746 {
747   //cout << "VISU_OpenGLPointSpriteMapper::DrawPoints" << endl;
748
749   //if( this->PrimitiveType == VISU_OpenGLPointSpriteMapper::OpenGLPoint )
750   //  glEnable( GL_POINT_SMOOTH );
751
752   glPointSize( this->DefaultPointSize );
753
754   TVertex* aVertexArr = new TVertex[ this->TotalCells ];
755
756   float* aPropertyColor = theActor->GetProperty()->GetColor();
757   float aColor[3] = {aPropertyColor[0], aPropertyColor[1], aPropertyColor[2]};
758
759   unsigned long i = 0;
760   vtkIdType *pts = 0;
761   vtkIdType npts = 0;
762   for( theCells->InitTraversal(); theCells->GetNextCell( npts, pts ); i++ )
763   {
764     TVertex& aVertex = aVertexArr[i];
765     vtkIdType aPointId = pts[0];
766     float* aCoords = thePoints->GetPoint( aPointId );
767     aVertex.vx = aCoords[0];
768     aVertex.vy = aCoords[1];
769     aVertex.vz = aCoords[2];
770
771     int aRed, aGreen, aBlue;
772     if( theColors && this->PointSpriteMode != 1 )
773     {
774       unsigned char *col = theColors->GetPointer(pts[0] << 2);
775       aRed = int(col[0]);
776       aGreen = int(col[1]);
777       aBlue = int(col[2]);
778
779       aColor[0] = aRed / 255.0;
780       aColor[1] = aGreen / 255.0;
781       aColor[2] = aBlue / 255.0;
782     }
783
784     aVertex.r = aColor[0];
785     aVertex.g = aColor[1];
786     aVertex.b = aColor[2];
787     aVertex.hue = ComputeHue( aRed, aGreen, aBlue );
788   }
789
790   GLuint aBufferObjectID = 0;
791   vglGenBuffersARB( 1, &aBufferObjectID );
792   vglBindBufferARB( GL_ARRAY_BUFFER_ARB, aBufferObjectID );
793
794   int nArrayObjectSize = sizeof( TVertex ) * this->TotalCells;
795   vglBufferDataARB( GL_ARRAY_BUFFER_ARB, nArrayObjectSize, aVertexArr, GL_STATIC_DRAW_ARB );
796
797   delete [] aVertexArr;
798
799   vglBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 );
800   vglBindBufferARB( GL_ARRAY_BUFFER_ARB, aBufferObjectID );
801
802   glColorPointer( 4, GL_FLOAT, sizeof(TVertex), (void*)0 );
803   glVertexPointer( 3, GL_FLOAT, sizeof(TVertex), (void*)(4*sizeof(GLfloat)) );
804
805   glEnableClientState( GL_VERTEX_ARRAY );
806   glEnableClientState( GL_COLOR_ARRAY );
807
808   glDrawArrays( GL_POINTS, 0, this->TotalCells );
809
810   glDisableClientState( GL_COLOR_ARRAY );
811   glDisableClientState( GL_VERTEX_ARRAY );
812
813   vglDeleteBuffersARB( 1, &aBufferObjectID );
814
815   //if( this->PrimitiveType == VISU_OpenGLPointSpriteMapper::OpenGLPoint )
816   //  glDisable( GL_POINT_SMOOTH );
817 }
818
819 //-----------------------------------------------------------------------------
820 int VISU_OpenGLPointSpriteMapper::Draw(vtkRenderer *aren, vtkActor *act)
821 {
822
823   if( this->UseOpenGLMapper ||
824       this->PrimitiveType == VISU_OpenGLPointSpriteMapper::GeomSphere )
825     return MAPPER_SUPERCLASS::Draw( aren, act );
826
827   vtkOpenGLRenderer    *ren    = (vtkOpenGLRenderer *)aren;
828   vtkUnsignedCharArray *colors = NULL;
829   vtkFloatArray        *alpha  = NULL;
830   vtkPolyData          *input  = this->GetInput();
831   vtkPoints            *points;
832   int noAbort = 1;
833   int cellScalars = 0;
834   vtkIdType cellNum = 0;
835   float  tran;
836
837   // get the transparency
838   tran = act->GetProperty()->GetOpacity();
839
840   // if the primitives are invisable then get out of here
841   if (tran <= 0.0)
842   {
843     return noAbort;
844   }
845
846   // and draw the display list
847   points = input->GetPoints();
848
849   // are they cell or point scalars
850   if ( this->Colors )
851   {
852     colors = this->Colors;
853     if ( (this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_DATA ||
854           this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_FIELD_DATA ||
855           !input->GetPointData()->GetScalars() )
856          && this->ScalarMode != VTK_SCALAR_MODE_USE_POINT_FIELD_DATA)
857     {
858       cellScalars = 1;
859     }
860   }
861
862   // we need to know the total number of cells so that we can report progress
863   this->TotalCells = input->GetVerts()->GetNumberOfCells();
864
865   this->DrawPoints(points, colors, alpha, cellNum, noAbort, input->GetVerts(), ren, act);
866
867   this->UpdateProgress(1.0);
868   return noAbort;
869 }
870 //-----------------------------------------------------------------------------
871 // Release the graphics resources used by this mapper.  In this case, release
872 // the display list if any.
873 void VISU_OpenGLPointSpriteMapper::ReleaseGraphicsResources(vtkWindow *win)
874 {
875   this->Superclass::ReleaseGraphicsResources(win);
876
877   if (this->ListId && win)
878     {
879     win->MakeCurrent();
880     glDeleteLists(this->ListId,1);
881     this->ListId = 0;
882     }
883   this->LastWindow = NULL;
884 }