Salome HOME
56c18d9330e6fd8edc590051614fdf6716038156
[modules/visu.git] / src / PIPELINE / VISU_OpenGLPointSpriteMapper.cxx
1 //  Copyright (C) 2007-2010  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  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.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 //  VISU OBJECT : interactive object for VISU entities implementation
24 // File:    VISU_OpenGLPointSpriteMapper.cxx
25 // Author:  
26 // Module : VISU
27 //
28 #include "VISU_OpenGLPointSpriteMapper.hxx"
29
30 //#include "SVTK_Extension.h"
31
32 #include <vtkCamera.h>
33 #include <vtkCellArray.h>
34 #include <vtkCellData.h>
35 #include <vtkCommand.h>
36 #include <vtkImageData.h>
37 #include <vtkMatrix4x4.h>
38 #include <vtkObjectFactory.h>
39 #include <vtkRenderer.h>
40 #include <vtkRenderWindow.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 <stdio.h>
49 #include <cmath>
50 #include <string>
51
52 #include "utilities.h"
53
54 #ifndef WNT
55 # ifndef GLX_GLXEXT_LEGACY
56 #  define GLX_GLXEXT_LEGACY
57 # endif
58 # include <GL/glx.h>
59 # include <dlfcn.h>
60 #else
61 # include <wingdi.h>
62 #endif
63
64 #ifndef VTK_IMPLEMENT_MESA_CXX
65 vtkCxxRevisionMacro(VISU_OpenGLPointSpriteMapper, "Revision$");
66 vtkStandardNewMacro(VISU_OpenGLPointSpriteMapper);
67 #endif
68
69 // some definitions for what the polydata has in it
70 #define VTK_PDPSM_COLORS             0x0001
71 #define VTK_PDPSM_CELL_COLORS        0x0002
72 #define VTK_PDPSM_POINT_TYPE_FLOAT   0x0004
73 #define VTK_PDPSM_POINT_TYPE_DOUBLE  0x0008
74 #define VTK_PDPSM_NORMAL_TYPE_FLOAT  0x0010
75 #define VTK_PDPSM_NORMAL_TYPE_DOUBLE 0x0020
76 #define VTK_PDPSM_OPAQUE_COLORS      0x0040
77
78 #ifndef APIENTRY
79 #define APIENTRY
80 #endif
81 #ifndef APIENTRYP
82 #define APIENTRYP APIENTRY *
83 #endif
84
85 #ifndef GL_OBJECT_INFO_LOG_LENGTH_ARB
86 #define GL_OBJECT_INFO_LOG_LENGTH_ARB     0x8B84
87 #endif
88
89 #ifndef GL_VERTEX_SHADER_ARB
90 #define GL_VERTEX_SHADER_ARB              0x8B31
91 #endif
92
93 #ifndef GL_VERTEX_PROGRAM_POINT_SIZE_ARB
94 #define GL_VERTEX_PROGRAM_POINT_SIZE_ARB  0x8642
95 #endif
96
97 #ifndef GL_ARB_point_sprite
98 #define GL_POINT_SPRITE_ARB               0x8861
99 #define GL_COORD_REPLACE_ARB              0x8862
100 #endif
101
102 #ifndef GL_ARB_shader_objects
103 typedef char GLcharARB;
104 #endif
105
106 #ifndef GL_ARB_vertex_buffer_object
107 typedef ptrdiff_t GLsizeiptrARB;
108
109 #define GL_ARRAY_BUFFER_ARB               0x8892
110 #define GL_STATIC_DRAW_ARB                0x88E4
111 #endif
112
113 typedef void (APIENTRYP PFNGLSHADERSOURCEARBPROC) (GLhandleARB shaderObj, GLsizei count, const GLcharARB* *string, const GLint *length);
114 typedef GLhandleARB (APIENTRYP PFNGLCREATESHADEROBJECTARBPROC) (GLenum shaderType);
115 typedef void (APIENTRYP PFNGLCOMPILESHADERARBPROC) (GLhandleARB shaderObj);
116 typedef GLhandleARB (APIENTRYP PFNGLCREATEPROGRAMOBJECTARBPROC) (void);
117 typedef void (APIENTRYP PFNGLATTACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB obj);
118 typedef void (APIENTRYP PFNGLLINKPROGRAMARBPROC) (GLhandleARB programObj);
119 typedef void (APIENTRYP PFNGLUSEPROGRAMOBJECTARBPROC) (GLhandleARB programObj);
120 typedef void (APIENTRYP PFNGLGETOBJECTPARAMETERIVARBPROC) (GLhandleARB obj, GLenum pname, GLint *params);
121 typedef void (APIENTRYP PFNGLGETINFOLOGARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *infoLog);
122 typedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB *name);
123 typedef void (APIENTRYP PFNGLVERTEXATTRIB1FARBPROC) (GLuint index, GLfloat x);
124
125 typedef void (APIENTRYP PFNGLBINDBUFFERARBPROC) (GLenum target, GLuint buffer);
126 typedef void (APIENTRYP PFNGLDELETEBUFFERSARBPROC) (GLsizei n, const GLuint *buffers);
127 typedef void (APIENTRYP PFNGLGENBUFFERSARBPROC) (GLsizei n, GLuint *buffers);
128 typedef void (APIENTRYP PFNGLBUFFERDATAARBPROC) (GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage);
129
130 static PFNGLSHADERSOURCEARBPROC             vglShaderSourceARB            = NULL;
131 static PFNGLCREATESHADEROBJECTARBPROC       vglCreateShaderObjectARB      = NULL;
132 static PFNGLCOMPILESHADERARBPROC            vglCompileShaderARB           = NULL;
133 static PFNGLCREATEPROGRAMOBJECTARBPROC      vglCreateProgramObjectARB     = NULL;
134 static PFNGLATTACHOBJECTARBPROC             vglAttachObjectARB            = NULL;
135 static PFNGLLINKPROGRAMARBPROC              vglLinkProgramARB             = NULL;
136 static PFNGLUSEPROGRAMOBJECTARBPROC         vglUseProgramObjectARB        = NULL;
137 static PFNGLGETOBJECTPARAMETERIVARBPROC     vglGetObjectParameterivARB    = NULL;
138 static PFNGLGETINFOLOGARBPROC               vglGetInfoLogARB              = NULL;
139 static PFNGLGETATTRIBLOCATIONARBPROC        vglGetAttribLocationARB       = NULL;
140 static PFNGLVERTEXATTRIB1FARBPROC           vglVertexAttrib1fARB          = NULL;
141
142 static PFNGLGENBUFFERSARBPROC               vglGenBuffersARB              = NULL;
143 static PFNGLBINDBUFFERARBPROC               vglBindBufferARB              = NULL;
144 static PFNGLBUFFERDATAARBPROC               vglBufferDataARB              = NULL;
145 static PFNGLDELETEBUFFERSARBPROC            vglDeleteBuffersARB           = NULL;
146
147 #ifndef WNT
148 #define GL_GetProcAddress( x )   glXGetProcAddressARB( (const GLubyte*)x )
149 #else
150 #define GL_GetProcAddress( x )   wglGetProcAddress( (const LPCSTR)x )
151 #endif
152
153 bool InitializeARB()
154 {
155   vglShaderSourceARB = (PFNGLSHADERSOURCEARBPROC)GL_GetProcAddress( "glShaderSourceARB" );
156   if( !vglShaderSourceARB )
157     return false;
158
159   vglCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC)GL_GetProcAddress( "glCreateShaderObjectARB" );
160   if( !vglCreateShaderObjectARB )
161     return false;
162
163   vglCompileShaderARB = (PFNGLCOMPILESHADERARBPROC)GL_GetProcAddress( "glCompileShaderARB" );
164   if( !vglCompileShaderARB )
165     return false;
166
167   vglCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC)GL_GetProcAddress( "glCreateProgramObjectARB" );
168   if( !vglCreateProgramObjectARB )
169     return false;
170
171   vglAttachObjectARB = (PFNGLATTACHOBJECTARBPROC)GL_GetProcAddress( "glAttachObjectARB" );
172   if( !vglAttachObjectARB )
173     return false;
174
175   vglLinkProgramARB = (PFNGLLINKPROGRAMARBPROC)GL_GetProcAddress( "glLinkProgramARB" );
176   if( !vglLinkProgramARB )
177     return false;
178
179   vglUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC)GL_GetProcAddress( "glUseProgramObjectARB" );
180   if( !vglUseProgramObjectARB )
181     return false;
182
183   vglGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC)GL_GetProcAddress( "glGetObjectParameterivARB" );
184   if( !vglGetObjectParameterivARB )
185     return false;
186
187   vglGetInfoLogARB = (PFNGLGETINFOLOGARBPROC)GL_GetProcAddress( "glGetInfoLogARB" );
188   if( !vglGetInfoLogARB )
189     return false;
190
191   vglGetAttribLocationARB = (PFNGLGETATTRIBLOCATIONARBPROC)GL_GetProcAddress( "glGetAttribLocationARB" );
192   if( !vglGetAttribLocationARB )
193     return false;
194
195   vglVertexAttrib1fARB = (PFNGLVERTEXATTRIB1FARBPROC)GL_GetProcAddress( "glVertexAttrib1fARB" );
196   if( !vglVertexAttrib1fARB )
197     return false;
198
199   vglGenBuffersARB = (PFNGLGENBUFFERSARBPROC)GL_GetProcAddress( "glGenBuffersARB" );
200   if( !vglGenBuffersARB )
201     return false;
202
203   vglBindBufferARB = (PFNGLBINDBUFFERARBPROC)GL_GetProcAddress( "glBindBufferARB" );
204   if( !vglBindBufferARB )
205     return false;
206
207   vglBufferDataARB = (PFNGLBUFFERDATAARBPROC)GL_GetProcAddress( "glBufferDataARB" );
208   if( !vglBufferDataARB )
209     return false;
210
211   vglDeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC)GL_GetProcAddress( "glDeleteBuffersARB" );
212   if( !vglDeleteBuffersARB )
213     return false;
214
215   return true;
216 };
217
218 static bool IsARBInitialized = InitializeARB();
219 static vtkFloatingPointType Tolerance = 1.0 / VTK_LARGE_FLOAT;
220
221 //-----------------------------------------------------------------------------
222 // Construct empty object.
223 VISU_OpenGLPointSpriteMapper::VISU_OpenGLPointSpriteMapper()
224 {
225   this->RenderMode               = VISU_OpenGLPointSpriteMapper::Occlude;
226
227   this->ListId                   = 0;
228   this->TotalCells               = 0;
229   this->ExtensionsInitialized    = 0;
230   this->DefaultPointSize         = 20.0;
231   this->AverageCellSize          = 0.0;
232
233   this->UsePointSprites          = true;
234   this->UseTextures              = true;
235   this->UseShader                = true;
236
237   this->PrimitiveType            = VISU_OpenGLPointSpriteMapper::PointSprite;
238
239   this->PointSpriteMode          = 0;
240
241   this->PointSpriteClamp         = 256.0;
242   this->PointSpriteSize          = 0.2;
243   this->PointSpriteMinSize       = 0.1;
244   this->PointSpriteMaxSize       = 0.3;
245   this->PointSpriteMagnification = 1.0;
246
247   this->PointSpriteAlphaThreshold = 0.5;
248   this->PointSpriteOpacity       = 1.0;
249   this->PointSpriteTexture       = 0;
250
251   this->UseOpenGLMapper          = false;
252 }
253 //-----------------------------------------------------------------------------
254 VISU_OpenGLPointSpriteMapper::~VISU_OpenGLPointSpriteMapper()
255 {
256   if( PointSpriteTexture>0 )
257     glDeleteTextures( 1, &PointSpriteTexture );
258
259   if( this->LastWindow )
260     this->ReleaseGraphicsResources(this->LastWindow);
261 }
262
263 //-----------------------------------------------------------------------------
264 char* readFromFile( std::string fileName )
265 {
266   FILE* file = fopen( fileName.c_str(), "r" );
267
268   char* content = NULL;
269   int count = 0;
270
271   if( file != NULL )
272   {
273     fseek( file, 0, SEEK_END );
274     count = ftell( file );
275     rewind( file );
276
277     if( count > 0 )
278     {
279       content = ( char* )malloc( sizeof( char ) * ( count + 1 ) );
280       count = fread( content, sizeof( char ), count, file );
281       content[ count ] = '\0';
282     }
283     fclose( file );
284   }
285
286   return content;
287 }
288 //-----------------------------------------------------------------------------
289 void VISU_OpenGLPointSpriteMapper::PrintInfoLog( GLhandleARB obj )
290 {
291   int infologLength = 0;
292   int charsWritten  = 0;
293   char* infoLog;
294
295   vglGetObjectParameterivARB( obj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &infologLength );
296
297   if( infologLength > 0 )
298   {
299     infoLog = ( char* )malloc( infologLength );
300     vglGetInfoLogARB( obj, infologLength, &charsWritten, infoLog );
301     printf( "%s\n", infoLog );
302     free( infoLog );
303   }
304 }
305 //-----------------------------------------------------------------------------
306 void VISU_OpenGLPointSpriteMapper::InitShader()
307 {
308   //cout << "Initializing vertex program" << endl;
309
310   std::string fileName = std::string( getenv( "VISU_ROOT_DIR") ) +
311                          "/share/salome/resources/visu/Vertex_Program_ARB.txt";
312
313   char* shader = readFromFile( fileName );
314
315   GLhandleARB VertexShader = vglCreateShaderObjectARB( GL_VERTEX_SHADER_ARB );
316   vglShaderSourceARB( VertexShader, 1, (const GLcharARB**)&shader, NULL );
317   vglCompileShaderARB( VertexShader );
318   //this->PrintInfoLog( VertexShader );
319
320   this->VertexProgram = vglCreateProgramObjectARB();
321   vglAttachObjectARB( this->VertexProgram, VertexShader );
322
323   vglLinkProgramARB( this->VertexProgram );
324   //this->PrintInfoLog( VertexProgram );
325   /*
326   cout << "Shader from " << fileName << endl;
327   for( int i = 0; i < strlen( shader ); i++ )
328     cout << shader[i];
329   cout << endl;
330
331   if( glGetError() == GL_NO_ERROR )
332     cout << "Loading vertex program... ok" << endl << endl;
333   else
334     cout << "Loading vertex program... failed" << endl << endl;
335   */
336   free( shader );
337 }
338
339 //-----------------------------------------------------------------------------
340 void VISU_OpenGLPointSpriteMapper::SetShaderVariable( const char* variable, float value )
341 {
342   //cout << this->VertexProgram << " ";
343   //cout << vglGetAttribLocationARB( this->VertexProgram, variable ) << " ";
344   //cout << variable << " " << value << endl;
345
346   vglVertexAttrib1fARB( vglGetAttribLocationARB( this->VertexProgram, variable ), value );
347 }
348
349 //-----------------------------------------------------------------------------
350 void VISU_OpenGLPointSpriteMapper::SetPrimitiveType( int thePrimitiveType )
351 {
352   if( this->PrimitiveType == thePrimitiveType )
353     return;
354
355   this->PrimitiveType = thePrimitiveType;
356   this->Modified();
357 }
358
359 //-----------------------------------------------------------------------------
360 void VISU_OpenGLPointSpriteMapper::SetPointSpriteMode( int theMode )
361 {
362   if( this->PointSpriteMode == theMode )
363     return;
364
365   this->PointSpriteMode = theMode;
366   this->Modified();
367 }
368
369 //-----------------------------------------------------------------------------
370 void VISU_OpenGLPointSpriteMapper::SetPointSpriteClamp( float theClamp )
371 {
372   if( fabs( this->PointSpriteClamp - theClamp ) < Tolerance )
373     return;
374
375   this->PointSpriteClamp = theClamp;
376   this->Modified();
377 }
378
379 //-----------------------------------------------------------------------------
380 void VISU_OpenGLPointSpriteMapper::SetAverageCellSize(float theSize)
381 {
382   if( fabs( this->AverageCellSize - theSize ) < Tolerance )
383     return;
384
385   this->AverageCellSize = theSize;
386   this->Modified();
387 }
388
389 //-----------------------------------------------------------------------------
390 void VISU_OpenGLPointSpriteMapper::SetPointSpriteSize( float theSize )
391 {
392   if( fabs( this->PointSpriteSize - theSize ) < Tolerance )
393     return;
394
395   this->PointSpriteSize = theSize;
396   this->Modified();
397 }
398
399 //-----------------------------------------------------------------------------
400 void VISU_OpenGLPointSpriteMapper::SetPointSpriteMinSize( float theMinSize )
401 {
402   if( fabs( this->PointSpriteMinSize - theMinSize ) < Tolerance )
403     return;
404
405   this->PointSpriteMinSize = theMinSize;
406   this->Modified();
407 }
408
409 //-----------------------------------------------------------------------------
410 void VISU_OpenGLPointSpriteMapper::SetPointSpriteMaxSize( float theMaxSize )
411 {
412   if( fabs( this->PointSpriteMaxSize - theMaxSize ) < Tolerance )
413     return;
414
415   this->PointSpriteMaxSize = theMaxSize;
416   this->Modified();
417 }
418
419 //-----------------------------------------------------------------------------
420 void VISU_OpenGLPointSpriteMapper::SetPointSpriteMagnification( float theMagnification )
421 {
422   if( fabs( this->PointSpriteMagnification - theMagnification ) < Tolerance )
423     return;
424
425   this->PointSpriteMagnification = theMagnification;
426   this->Modified();
427 }
428
429 //-----------------------------------------------------------------------------
430 void VISU_OpenGLPointSpriteMapper::SetPointSpriteAlphaThreshold( float theAlphaThreshold )
431 {
432   if( fabs( this->PointSpriteAlphaThreshold - theAlphaThreshold ) < Tolerance )
433     return;
434
435   this->PointSpriteAlphaThreshold = theAlphaThreshold;
436   this->Modified();
437 }
438
439 //-----------------------------------------------------------------------------
440 bool VISU_OpenGLPointSpriteMapper::InitExtensions()
441 {
442   if( this->ExtensionsInitialized )
443     return true;
444
445   InitializeARB();
446
447   char* ext = (char*)glGetString( GL_EXTENSIONS );
448   //cout << "OpenGL extensions : " << ext << endl;
449
450   if( !IsARBInitialized ||
451       strstr( ext, "GL_ARB_point_sprite" ) == NULL ||
452       strstr( ext, "GL_ARB_shader_objects" ) == NULL ||
453       strstr( ext, "GL_ARB_vertex_buffer_object" ) == NULL )
454   {
455     vtkWarningMacro(<<"Initializing ARB extensions failed");
456     this->UseOpenGLMapper = true;
457
458     return false;
459   }
460
461   if( this->UseShader )
462     this->InitShader();
463
464   this->ExtensionsInitialized = 1;
465   return true;
466 }
467
468 //-----------------------------------------------------------------------------
469 float ViewToDisplay( vtkRenderer* theRenderer )
470 {
471   vtkFloatingPointType p1[3], p2[3];
472
473   theRenderer->SetViewPoint( 0.0, 0.0, 0.0 );
474   theRenderer->ViewToDisplay();
475   theRenderer->GetDisplayPoint( p1 );
476
477   theRenderer->SetViewPoint( 1.0, 1.0, 1.0 );
478   theRenderer->ViewToDisplay();
479   theRenderer->GetDisplayPoint( p2 );
480
481   vtkFloatingPointType coefficient = sqrt( pow( p2[0] - p1[0], 2 ) + pow( p2[1] - p1[1], 2 ) ) / sqrt( 2. );
482   //cout << p1[0] << " " << p1[1] << " " << p1[2] << endl;
483   //cout << p2[0] << " " << p2[1] << " " << p2[2] << endl;
484   //cout << "ZOOM  : " << coefficient << endl;
485
486   return coefficient;
487 }
488
489 //-----------------------------------------------------------------------------
490 //
491 // Receives from Actor -> maps data to primitives
492 //
493 void VISU_OpenGLPointSpriteMapper::RenderPiece(vtkRenderer *ren, vtkActor *act)
494 {
495   bool isUseThisMapper = this->PrimitiveType != VISU_OpenGLPointSpriteMapper::GeomSphere;
496
497   if( isUseThisMapper )
498     this->InitExtensions();
499
500   if( !isUseThisMapper )
501   {
502     MAPPER_SUPERCLASS::RenderPiece( ren, act );
503     return;
504   }
505
506   vtkIdType numPts;
507   vtkPolyData *input= this->GetInput();
508
509   //
510   // make sure that we've been properly initialized
511   //
512   if (ren->GetRenderWindow()->CheckAbortStatus())
513     return;
514
515   if ( input == NULL )
516   {
517     vtkErrorMacro(<< "No input!");
518     return;
519   }
520   else
521   {
522     this->InvokeEvent(vtkCommand::StartEvent,NULL);
523     input->Update();
524     this->InvokeEvent(vtkCommand::EndEvent,NULL);
525
526     numPts = input->GetNumberOfPoints();
527   }
528
529   if (numPts == 0)
530   {
531     vtkDebugMacro(<< "No points!");
532     return;
533   }
534
535   if ( this->LookupTable == NULL )
536     this->CreateDefaultLookupTable();
537
538   // make sure our window is current
539   ren->GetRenderWindow()->MakeCurrent();
540
541   if( this->UsePointSprites ) //&& this->PrimitiveType == VISU_OpenGLPointSpriteMapper::PointSprite )
542     this->InitPointSprites();
543
544   // Initializing the texture for Point Sprites
545   if( this->UseTextures && this->PrimitiveType == VISU_OpenGLPointSpriteMapper::PointSprite )
546     this->InitTextures();
547
548   vglUseProgramObjectARB( this->VertexProgram );
549   float aViewToDisplay = ViewToDisplay( ren );
550   this->SetShaderVariable( "mode",          this->PointSpriteMode );
551   this->SetShaderVariable( "clampSize",     this->PointSpriteClamp );
552   this->SetShaderVariable( "geomSize",      aViewToDisplay * this->AverageCellSize * this->PointSpriteSize );
553   this->SetShaderVariable( "minSize",       aViewToDisplay * this->AverageCellSize * this->PointSpriteMinSize );
554   this->SetShaderVariable( "maxSize",       aViewToDisplay * this->AverageCellSize * this->PointSpriteMaxSize );
555   this->SetShaderVariable( "magnification", this->PointSpriteMagnification );
556
557   //
558   // if something has changed regenerate colors and display lists
559   // if required
560   //
561   int noAbort=1;
562   if ( this->GetMTime() > this->BuildTime ||
563        input->GetMTime() > this->BuildTime ||
564        act->GetProperty()->GetMTime() > this->BuildTime ||
565        ren->GetRenderWindow() != this->LastWindow)
566   {
567 #ifdef _DEBUG_RENDERING_PERFORMANCE_
568     // To control when the mapper is recalculated
569     MESSAGE( "VISU_OpenGLPointSpriteMapper::RenderPiece - "
570              <<(this->GetMTime() > this->BuildTime)<<"; "
571              <<(input->GetMTime() > this->BuildTime)<<"; "
572              <<(act->GetProperty()->GetMTime() > this->BuildTime)<<"; ");
573 #endif
574     // sets this->Colors as side effect
575     this->MapScalars( act->GetProperty()->GetOpacity() );
576
577     if (!this->ImmediateModeRendering &&
578         !this->GetGlobalImmediateModeRendering())
579     {
580       this->ReleaseGraphicsResources(ren->GetRenderWindow());
581       this->LastWindow = ren->GetRenderWindow();
582
583       // get a unique display list id
584       this->ListId = glGenLists(1);
585       glNewList(this->ListId,GL_COMPILE);
586
587       noAbort = this->Draw(ren,act);
588       glEndList();
589
590       // Time the actual drawing
591       this->Timer->StartTimer();
592       glCallList(this->ListId);
593       this->Timer->StopTimer();
594     }
595     else
596     {
597       this->ReleaseGraphicsResources(ren->GetRenderWindow());
598       this->LastWindow = ren->GetRenderWindow();
599     }
600     if (noAbort)
601       this->BuildTime.Modified();
602   }
603   // if nothing changed but we are using display lists, draw it
604   else
605   {
606     if (!this->ImmediateModeRendering &&
607         !this->GetGlobalImmediateModeRendering())
608     {
609       // Time the actual drawing
610       this->Timer->StartTimer();
611       glCallList(this->ListId);
612       this->Timer->StopTimer();
613     }
614   }
615
616   // if we are in immediate mode rendering we always
617   // want to draw the primitives here
618   if (this->ImmediateModeRendering ||
619       this->GetGlobalImmediateModeRendering())
620   {
621     // sets this->Colors as side effect
622     this->MapScalars( act->GetProperty()->GetOpacity() );
623
624     // Time the actual drawing
625     this->Timer->StartTimer();
626     this->Draw(ren,act);
627     this->Timer->StopTimer();
628   }
629
630   this->TimeToDraw = (float)this->Timer->GetElapsedTime();
631
632   // If the timer is not accurate enough, set it to a small
633   // time so that it is not zero
634   if ( this->TimeToDraw == 0.0 )
635     this->TimeToDraw = 0.0001;
636
637   vglUseProgramObjectARB( 0 );
638
639   if( this->UsePointSprites ) //&& this->PrimitiveType == VISU_OpenGLPointSpriteMapper::PointSprite )
640     this->CleanupPointSprites();
641 }
642
643 //-----------------------------------------------------------------------------
644 float VISU_OpenGLPointSpriteMapper::GetMaximumSupportedSize()
645 {
646   float maximumSupportedSize = 512.0;
647   //glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maximumSupportedSize );
648
649   return maximumSupportedSize;
650 }
651
652 //-----------------------------------------------------------------------------
653 void VISU_OpenGLPointSpriteMapper::InitPointSprites()
654 {
655   glEnable( GL_POINT_SPRITE_ARB );
656   glEnable( GL_VERTEX_PROGRAM_POINT_SIZE_ARB );
657
658   glPushAttrib( GL_COLOR_BUFFER_BIT | GL_CURRENT_BIT | GL_DEPTH_BUFFER_BIT | GL_ENABLE_BIT | GL_LIGHTING_BIT );
659
660   this->RenderMode = this->PointSpriteOpacity < 1.0 ? VISU_OpenGLPointSpriteMapper::Accumulate : VISU_OpenGLPointSpriteMapper::Occlude;
661
662   switch (this->RenderMode)
663   {
664     case VISU_OpenGLPointSpriteMapper::Accumulate:
665     {
666       glDepthFunc( GL_LESS );
667       glEnable( GL_DEPTH_TEST );
668
669       glEnable( GL_BLEND );
670       glBlendFunc( GL_SRC_ALPHA, GL_ONE );
671
672       glEnable( GL_ALPHA_TEST );
673       glAlphaFunc( GL_GREATER, this->PointSpriteAlphaThreshold );
674       break;
675     }
676
677     case VISU_OpenGLPointSpriteMapper::Occlude:
678     {
679       glDepthFunc( GL_LEQUAL );
680       glEnable( GL_DEPTH_TEST );
681
682       glEnable( GL_ALPHA_TEST );
683       glAlphaFunc( GL_GREATER, this->PointSpriteAlphaThreshold );
684
685       glDisable( GL_BLEND );
686       break;
687     }
688
689     default:
690     {
691       break;
692     }
693   }
694   // Disable Lighting/Shading.
695   glDisable( GL_LIGHTING );
696
697   // Disable material properties
698   glDisable( GL_COLOR_MATERIAL );
699 }
700
701 //-----------------------------------------------------------------------------
702 void VISU_OpenGLPointSpriteMapper::CleanupPointSprites()
703 {
704   // Set GL params back to normal to stop other vtkMappers displaying wrongly
705   glPopAttrib();
706
707   glDisable( GL_VERTEX_PROGRAM_POINT_SIZE_ARB );
708   glDisable( GL_POINT_SPRITE_ARB );
709 }
710
711
712 //-----------------------------------------------------------------------------
713 void
714 VISU_OpenGLPointSpriteMapper
715 ::SetImageData( vtkImageData* theImageData )
716 {
717   if(GetImageData() == theImageData)
718     return;
719   this->ImageData = theImageData;
720   this->Modified();
721 }
722
723 vtkImageData*
724 VISU_OpenGLPointSpriteMapper
725 ::GetImageData()
726 {
727   return this->ImageData.GetPointer();
728 }
729
730
731 //-----------------------------------------------------------------------------
732 void VISU_OpenGLPointSpriteMapper::InitTextures()
733 {
734   //cout << "VISU_OpenGLPointSpriteMapper::InitTextures " << this->GetImageData() << endl;
735   if( !this->GetImageData() )
736     return;
737
738   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
739   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
740   glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
741   glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
742
743   int* aSize = GetImageData()->GetDimensions();
744   unsigned char* dataPtr = (unsigned char*)GetImageData()->GetScalarPointer();
745   glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, aSize[0], aSize[1], 0,
746                 GL_RGBA, GL_UNSIGNED_BYTE, dataPtr );
747
748   //glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
749   glEnable( GL_TEXTURE_2D );
750   glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE );
751   glBindTexture( GL_TEXTURE_2D, this->PointSpriteTexture );
752 }
753
754
755 //-----------------------------------------------------------------------------
756 int ComputeHue( int r, int g, int b )
757 {
758   int h = 0;
759
760   int max = r;
761   int whatmax = 0;
762   if( g > max ) {
763     max = g;
764     whatmax = 1;
765   }
766   if( b > max ) {
767     max = b;
768     whatmax = 2;
769   }
770
771   int min = r;
772   if ( g < min ) min = g;
773   if ( b < min ) min = b;
774   int delta = max-min;
775
776   if( delta == 0 )
777     h = 0;
778   else if( whatmax == 0 ) {
779     if ( g >= b )
780       h = (120*(g-b)+delta)/(2*delta);
781     else
782       h = (120*(g-b+delta)+delta)/(2*delta) + 300;
783   }
784   else if( whatmax == 1 ) {
785     if ( b > r )
786       h = 120 + (120*(b-r)+delta)/(2*delta);
787     else
788       h = 60 + (120*(b-r+delta)+delta)/(2*delta);
789   }
790   else {
791     if ( r > g )
792       h = 240 + (120*(r-g)+delta)/(2*delta);
793     else
794       h = 180 + (120*(r-g+delta)+delta)/(2*delta);
795   }
796
797   return h + 1;
798 }
799
800 //-----------------------------------------------------------------------------
801 struct TVertex
802 {
803   GLfloat r, g, b, hue;
804   GLfloat vx, vy, vz;
805 };
806
807
808 //-----------------------------------------------------------------------------
809 struct TColorFunctorBase
810 {
811   virtual
812   void
813   get( TVertex& theVertex, vtkIdType thePointId, vtkIdType theCellId ) = 0;
814 };
815
816
817 //-----------------------------------------------------------------------------
818 struct TPropertyColor : TColorFunctorBase
819 {
820   vtkFloatingPointType myColor[3];
821   vtkFloatingPointType myHue;
822
823   TPropertyColor( vtkProperty *theProperty )
824   {
825     theProperty->GetColor( myColor );
826     int aRed = int( myColor[0] * 255 );
827     int aGreen = int( myColor[1] * 255 );
828     int aBlue = int( myColor[2] * 255 );
829
830     myHue = ComputeHue( aRed, aGreen, aBlue );
831   }
832
833   virtual
834   void
835   get( TVertex& theVertex, vtkIdType thePointId, vtkIdType theCellId )
836   {
837     theVertex.r = myColor[0];
838     theVertex.g = myColor[1];
839     theVertex.b = myColor[2];
840
841     theVertex.hue = myHue;
842   }
843 };
844
845
846 //-----------------------------------------------------------------------------
847 struct TColors2Color : TColorFunctorBase
848 {
849   vtkUnsignedCharArray *myColors;
850
851   TColors2Color( vtkUnsignedCharArray *theColors ):
852     myColors( theColors )
853   {}
854
855   virtual
856   void
857   get( TVertex& theVertex, vtkIdType thePointId, vtkIdType theCellId )
858   {
859     vtkIdType aTupleId = GetTupleId( thePointId, theCellId );
860     unsigned char *aColor = myColors->GetPointer( aTupleId << 2 );
861
862     theVertex.r = int( aColor[0] ) / 255.0;
863     theVertex.g = int( aColor[1] ) / 255.0;
864     theVertex.b = int( aColor[2] ) / 255.0;
865
866     theVertex.hue = ComputeHue( aColor[0], aColor[1], aColor[2] );
867   }  
868
869   virtual
870   vtkIdType
871   GetTupleId( vtkIdType thePointId, vtkIdType theCellId ) = 0;
872 };
873
874
875 //-----------------------------------------------------------------------------
876 struct TPointColors2Color : TColors2Color
877 {
878   TPointColors2Color( vtkUnsignedCharArray *theColors ):
879     TColors2Color( theColors )
880   {}
881
882   virtual
883   vtkIdType
884   GetTupleId( vtkIdType thePointId, vtkIdType theCellId )
885   {
886     return thePointId;
887   }
888 };
889
890
891 //-----------------------------------------------------------------------------
892 struct TCellColors2Color : TColors2Color
893 {
894   TCellColors2Color( vtkUnsignedCharArray *theColors ):
895     TColors2Color( theColors )
896   {}
897
898   virtual
899   vtkIdType
900   GetTupleId( vtkIdType thePointId, vtkIdType theCellId )
901   {
902     return theCellId;
903   }
904 };
905
906
907 //-----------------------------------------------------------------------------
908 template < class TCoordinates >
909 void DrawPoints( TCoordinates *theStartPoints,
910                  vtkCellArray *theCells,
911                  TColorFunctorBase* theColorFunctor,
912                  TVertex* theVertexArr,
913                  vtkIdType &theCellId,
914                  vtkIdType &theVertexId )
915 {
916   vtkIdType *ptIds = theCells->GetPointer();
917   vtkIdType *endPtIds = ptIds + theCells->GetNumberOfConnectivityEntries();
918
919   while ( ptIds < endPtIds ) {
920     vtkIdType nPts = *ptIds;
921     ++ptIds;
922
923     while ( nPts > 0 ) {
924       TVertex& aVertex = theVertexArr[ theVertexId ];
925       vtkIdType aPointId = *ptIds;
926
927       TCoordinates *anOffsetPoints = theStartPoints + 3 * aPointId;
928       aVertex.vx = anOffsetPoints[0];
929       aVertex.vy = anOffsetPoints[1];
930       aVertex.vz = anOffsetPoints[2];
931
932       theColorFunctor->get( aVertex, aPointId, theCellId );
933
934       ++theVertexId;
935       ++ptIds; 
936       --nPts; 
937     }
938
939     ++theCellId;
940   }
941 }
942
943
944 //-----------------------------------------------------------------------------
945 template < class TCoordinates >
946 void DrawCellsPoints( vtkPolyData *theInput,
947                       vtkPoints* thePoints,
948                       TColorFunctorBase* theColorFunctor,
949                       TVertex* theVertexArr )
950 {
951   vtkIdType aCellId = 0, aVertexId = 0;
952
953   TCoordinates *aStartPoints = (TCoordinates *) thePoints->GetVoidPointer(0);
954
955   if ( vtkCellArray* aCellArray = theInput->GetVerts() )
956     DrawPoints( aStartPoints, aCellArray, theColorFunctor, theVertexArr, aCellId, aVertexId );
957   
958   if ( vtkCellArray* aCellArray = theInput->GetLines() )
959     DrawPoints( aStartPoints, aCellArray, theColorFunctor, theVertexArr, aCellId, aVertexId );
960   
961   if ( vtkCellArray* aCellArray = theInput->GetPolys() )
962     DrawPoints( aStartPoints, aCellArray, theColorFunctor, theVertexArr, aCellId, aVertexId );
963   
964   if ( vtkCellArray* aCellArray = theInput->GetStrips() )
965     DrawPoints( aStartPoints, aCellArray, theColorFunctor, theVertexArr, aCellId, aVertexId ); 
966 }
967
968
969 //-----------------------------------------------------------------------------
970 int VISU_OpenGLPointSpriteMapper::Draw(vtkRenderer *theRenderer, vtkActor *theActor)
971 {
972
973   if( this->PrimitiveType == VISU_OpenGLPointSpriteMapper::GeomSphere )
974     return MAPPER_SUPERCLASS::Draw( theRenderer, theActor );
975
976   vtkUnsignedCharArray *colors = NULL;
977   vtkPolyData          *input  = this->GetInput();
978   vtkPoints            *points;
979   int noAbort = 1;
980   int cellScalars = 0;
981
982   // if the primitives are invisable then get out of here
983   if (this->PointSpriteOpacity <= 0.0)
984   {
985     return noAbort;
986   }
987
988   // and draw the display list
989   points = input->GetPoints();
990
991   // are they cell or point scalars
992   if ( this->Colors )
993   {
994     colors = this->Colors;
995     if ( (this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_DATA ||
996           this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_FIELD_DATA ||
997           !input->GetPointData()->GetScalars() )
998          && this->ScalarMode != VTK_SCALAR_MODE_USE_POINT_FIELD_DATA)
999     {
1000       cellScalars = 1;
1001     }
1002   }
1003
1004   {
1005     vtkIdType aTotalConnectivitySize = 0;
1006
1007     if ( vtkCellArray* aCellArray = input->GetVerts() )
1008       aTotalConnectivitySize += aCellArray->GetNumberOfConnectivityEntries() - aCellArray->GetNumberOfCells();
1009
1010     if ( vtkCellArray* aCellArray = input->GetLines() )
1011       aTotalConnectivitySize += aCellArray->GetNumberOfConnectivityEntries() - aCellArray->GetNumberOfCells();
1012
1013     if ( vtkCellArray* aCellArray = input->GetPolys() )
1014       aTotalConnectivitySize += aCellArray->GetNumberOfConnectivityEntries() - aCellArray->GetNumberOfCells();
1015
1016     if ( vtkCellArray* aCellArray = input->GetStrips() )
1017       aTotalConnectivitySize += aCellArray->GetNumberOfConnectivityEntries() - aCellArray->GetNumberOfCells();
1018
1019     if ( aTotalConnectivitySize > 0 ) {
1020       TVertex* aVertexArr = new TVertex[ aTotalConnectivitySize ];
1021
1022       vtkFloatingPointType aPropertyColor[3];
1023       theActor->GetProperty()->GetColor( aPropertyColor );
1024
1025       glPointSize( this->DefaultPointSize );
1026
1027       {
1028         TColorFunctorBase* aColorFunctor = NULL;
1029         if( colors && this->PointSpriteMode != 1 ) {
1030           if ( cellScalars )
1031             aColorFunctor = new TCellColors2Color( colors );
1032           else
1033             aColorFunctor = new TPointColors2Color( colors );
1034         } else {
1035           aColorFunctor = new TPropertyColor( theActor->GetProperty() );
1036         }
1037         if ( points->GetDataType() == VTK_FLOAT )
1038           ::DrawCellsPoints< float >( input, points, aColorFunctor, aVertexArr );
1039         else
1040           ::DrawCellsPoints< double >( input, points, aColorFunctor, aVertexArr );
1041
1042         delete aColorFunctor;
1043       }
1044
1045       if( this->ExtensionsInitialized ) {
1046         GLuint aBufferObjectID = 0;
1047         vglGenBuffersARB( 1, &aBufferObjectID );
1048         vglBindBufferARB( GL_ARRAY_BUFFER_ARB, aBufferObjectID );
1049         
1050         int anArrayObjectSize = sizeof( TVertex ) * aTotalConnectivitySize;
1051         vglBufferDataARB( GL_ARRAY_BUFFER_ARB, anArrayObjectSize, aVertexArr, GL_STATIC_DRAW_ARB );
1052         
1053         delete [] aVertexArr;
1054         
1055         vglBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 );
1056         vglBindBufferARB( GL_ARRAY_BUFFER_ARB, aBufferObjectID );
1057         
1058         glColorPointer( 4, GL_FLOAT, sizeof(TVertex), (void*)0 );
1059         glVertexPointer( 3, GL_FLOAT, sizeof(TVertex), (void*)(4*sizeof(GLfloat)) );
1060         
1061         glEnableClientState( GL_VERTEX_ARRAY );
1062         glEnableClientState( GL_COLOR_ARRAY );
1063         
1064         glDrawArrays( GL_POINTS, 0, aTotalConnectivitySize );
1065         
1066         glDisableClientState( GL_COLOR_ARRAY );
1067         glDisableClientState( GL_VERTEX_ARRAY );
1068         
1069         vglDeleteBuffersARB( 1, &aBufferObjectID );
1070       } else { // there are not extensions
1071         glColorPointer( 4, GL_FLOAT, sizeof(TVertex), aVertexArr );
1072         glVertexPointer( 3, GL_FLOAT, sizeof(TVertex), 
1073                          (void*)((GLfloat*)((void*)(aVertexArr)) + 4));
1074
1075         glEnableClientState( GL_VERTEX_ARRAY );
1076         glEnableClientState( GL_COLOR_ARRAY );
1077         
1078         glDrawArrays( GL_POINTS, 0, aTotalConnectivitySize );
1079         
1080         glDisableClientState( GL_COLOR_ARRAY );
1081         glDisableClientState( GL_VERTEX_ARRAY );
1082
1083         delete [] aVertexArr;
1084       }
1085     }
1086
1087     input->GetVerts()->GetNumberOfCells() + 
1088     input->GetLines()->GetNumberOfCells() + 
1089     input->GetPolys()->GetNumberOfCells() + 
1090     input->GetStrips()->GetNumberOfCells();
1091   }
1092
1093
1094   this->UpdateProgress(1.0);
1095   return noAbort;
1096 }
1097 //-----------------------------------------------------------------------------
1098 // Release the graphics resources used by this mapper.  In this case, release
1099 // the display list if any.
1100 void VISU_OpenGLPointSpriteMapper::ReleaseGraphicsResources(vtkWindow *win)
1101 {
1102   this->Superclass::ReleaseGraphicsResources(win);
1103
1104   if (this->ListId && win)
1105     {
1106     win->MakeCurrent();
1107     glDeleteLists(this->ListId,1);
1108     this->ListId = 0;
1109     }
1110   this->LastWindow = NULL;
1111 }