1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkStructuredGridLIC2D.cxx
5 
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10      This software is distributed WITHOUT ANY WARRANTY; without even
11      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12      PURPOSE.  See the above copyright notice for more information.
13 
14 =========================================================================*/
15 #include "vtkStructuredGridLIC2D.h"
16 
17 #include "vtkFloatArray.h"
18 #include "vtkImageData.h"
19 #include "vtkImageNoiseSource.h"
20 #include "vtkInformation.h"
21 #include "vtkInformationVector.h"
22 #include "vtkDataTransferHelper.h"
23 #include "vtkFrameBufferObject.h"
24 #include "vtkLineIntegralConvolution2D.h"
25 #include "vtkShaderProgram2.h"
26 #include "vtkShader2.h"
27 #include "vtkShader2Collection.h"
28 #include "vtkUniformVariables.h"
29 #include "vtkStructuredExtent.h"
30 #include "vtkTextureObject.h"
31 #include "vtkObjectFactory.h"
32 #include "vtkOpenGLExtensionManager.h"
33 #include "vtkOpenGLRenderWindow.h"
34 #include "vtkPointData.h"
35 #include "vtkStreamingDemandDrivenPipeline.h"
36 #include "vtkOpenGLError.h"
37 
38 #include "vtkPixelExtent.h"
39 #include "vtkPixelTransfer.h"
40 #include "vtkPixelBufferObject.h"
41 
42 #include <cassert>
43 #include "vtkgl.h"
44 
45 extern const char *vtkStructuredGridLIC2D_fs;
46 
47 #define PRINTEXTENT(ext) \
48   ext[0] << ", " << ext[1] << ", " << ext[2] << ", " << ext[3] << ", " << ext[4] << ", " << ext[5]
49 
50 vtkStandardNewMacro(vtkStructuredGridLIC2D);
51 //----------------------------------------------------------------------------
vtkStructuredGridLIC2D()52 vtkStructuredGridLIC2D::vtkStructuredGridLIC2D()
53 {
54   this->Context = 0;
55   this->Steps = 1;
56   this->StepSize = 1.0;
57   this->Magnification = 1;
58   this->SetNumberOfInputPorts(2);
59   this->SetNumberOfOutputPorts(2);
60   this->OwnWindow  = false;
61   this->FBOSuccess = 0;
62   this->LICSuccess = 0;
63   this->OpenGLExtensionsSupported = 0;
64 
65   this->NoiseSource = vtkImageNoiseSource::New();
66   this->NoiseSource->SetWholeExtent(0, 127, 0, 127, 0, 0);
67   this->NoiseSource->SetMinimum(0.0);
68   this->NoiseSource->SetMaximum(1.0);
69 }
70 
71 //----------------------------------------------------------------------------
~vtkStructuredGridLIC2D()72 vtkStructuredGridLIC2D::~vtkStructuredGridLIC2D()
73 {
74   this->NoiseSource->Delete();
75   this->SetContext( NULL );
76 }
77 
78 //----------------------------------------------------------------------------
GetContext()79 vtkRenderWindow* vtkStructuredGridLIC2D::GetContext()
80 {
81   return this->Context;
82 }
83 
84 //----------------------------------------------------------------------------
SetContext(vtkRenderWindow * context)85 int vtkStructuredGridLIC2D::SetContext( vtkRenderWindow * context )
86 {
87   if ( this->Context == context )
88     {
89     return this->OpenGLExtensionsSupported;
90     }
91 
92   if ( this->Context && this->OwnWindow )
93     {
94     this->Context->Delete();
95     this->Context = NULL;
96     }
97   this->OwnWindow = false;
98 
99 
100   vtkOpenGLRenderWindow * openGLRenWin =
101   vtkOpenGLRenderWindow::SafeDownCast( context );
102   this->Context = openGLRenWin;
103 
104   if ( openGLRenWin )
105     {
106     vtkOpenGLExtensionManager * mgr = openGLRenWin->GetExtensionManager();
107 
108     // optional for texture objects.
109     mgr->LoadSupportedExtension( "GL_EXT_texture_integer" );
110 
111     if (  !mgr->LoadSupportedExtension( "GL_VERSION_1_3" ) ||
112           !mgr->LoadSupportedExtension( "GL_VERSION_1_2" ) ||
113           !mgr->LoadSupportedExtension( "GL_VERSION_2_0" ) ||
114           !mgr->LoadSupportedExtension( "GL_ARB_texture_float" ) ||
115           !mgr->LoadSupportedExtension( "GL_ARB_color_buffer_float" ) ||
116           !mgr->LoadSupportedExtension( "GL_ARB_texture_non_power_of_two" )
117        )
118       {
119       vtkErrorMacro( "Required OpenGL extensions not supported." );
120       mgr = NULL;
121       this->Context = 0;
122       openGLRenWin  = NULL;
123       return 0;
124       }
125 
126     mgr = NULL;
127     }
128 
129   openGLRenWin = NULL;
130   this->Modified();
131 
132   this->OpenGLExtensionsSupported = 1;
133   return 1;
134 }
135 
136 //----------------------------------------------------------------------------
137 // Description:
138 // Fill the input port information objects for this algorithm.  This
139 // is invoked by the first call to GetInputPortInformation for each
140 // port so subclasses can specify what they can handle.
141 // Redefined from the superclass.
FillInputPortInformation(int port,vtkInformation * info)142 int vtkStructuredGridLIC2D::FillInputPortInformation
143   ( int port, vtkInformation * info )
144 {
145   if ( port == 0 )
146     {
147     info->Set( vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkStructuredGrid" );
148     info->Set( vtkAlgorithm::INPUT_IS_REPEATABLE(), 0 );
149     info->Set( vtkAlgorithm::INPUT_IS_OPTIONAL(),   0 );
150     }
151   else
152     {
153     info->Set( vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkImageData" );
154     info->Set( vtkAlgorithm::INPUT_IS_REPEATABLE(), 0 );
155     info->Set( vtkAlgorithm::INPUT_IS_OPTIONAL(),   1 );
156     }
157 
158   return 1;
159 }
160 
161 // ----------------------------------------------------------------------------
162 // Description:
163 // Fill the output port information objects for this algorithm.
164 // This is invoked by the first call to GetOutputPortInformation for
165 // each port so subclasses can specify what they can handle.
166 // Redefined from the superclass.
FillOutputPortInformation(int port,vtkInformation * info)167 int vtkStructuredGridLIC2D::FillOutputPortInformation
168   ( int port, vtkInformation * info )
169 {
170   if ( port == 0 )
171     {
172     // input+texcoords
173     info->Set( vtkDataObject::DATA_TYPE_NAME(), "vtkStructuredGrid" );
174     }
175   else
176     {
177     // LIC texture
178     info->Set( vtkDataObject::DATA_TYPE_NAME(), "vtkImageData" );
179     }
180 
181   return 1;
182 }
183 //----------------------------------------------------------------------------
184 // We need to report output extent after taking into consideration the
185 // magnification.
RequestInformation(vtkInformation * vtkNotUsed (request),vtkInformationVector ** inputVector,vtkInformationVector * outputVector)186 int vtkStructuredGridLIC2D::RequestInformation(
187   vtkInformation        * vtkNotUsed(request),
188   vtkInformationVector ** inputVector,
189   vtkInformationVector  * outputVector )
190 {
191   int ext[6];
192   double spacing[3];
193 
194   vtkInformation * inInfo  = inputVector[0]->GetInformationObject( 0 );
195   vtkInformation * outInfo = outputVector->GetInformationObject( 1 );
196 
197   inInfo->Get( vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), ext );
198 
199   spacing[0] = 1.0;
200   spacing[1] = 1.0;
201   spacing[2] = 1.0;
202 
203   for (int axis = 0; axis < 3; axis++)
204     {
205     int wholeMin = ext[axis*2];
206     int wholeMax = ext[axis*2+1];
207     int dimension = wholeMax - wholeMin + 1;
208 
209     // Scale the output extent
210     wholeMin = static_cast<int>(  ceil( static_cast<double>
211                                         ( wholeMin * this->Magnification )
212                                       )
213                                );
214     wholeMax = ( dimension != 1 )
215                ? wholeMin + static_cast<int>
216                  (   floor(  static_cast<double>
217                              ( dimension * this->Magnification )
218                           )
219                  ) -1
220                : wholeMin;
221 
222     ext[ axis * 2     ] = wholeMin;
223     ext[ axis * 2 + 1 ] = wholeMax;
224     }
225 
226   vtkDebugMacro( << "request info whole ext = " << PRINTEXTENT( ext ) << endl );
227 
228   outInfo->Set( vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), ext, 6 );
229   outInfo->Set( vtkDataObject::SPACING(), spacing, 3 );
230 
231   return 1;
232 }
233 
234 //----------------------------------------------------------------------------
RequestUpdateExtent(vtkInformation * vtkNotUsed (request),vtkInformationVector ** inputVector,vtkInformationVector * outputVector)235 int vtkStructuredGridLIC2D::RequestUpdateExtent (
236   vtkInformation * vtkNotUsed(request),
237   vtkInformationVector **inputVector,
238   vtkInformationVector *outputVector)
239 {
240   vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
241   vtkInformation *outInfo = outputVector->GetInformationObject(1);
242 
243 
244   // Tell the vector field input the extents that we need from it.
245   // The downstream request needs to be downsized based on the Magnification.
246   int ext[6];
247   outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), ext);
248 
249   vtkDebugMacro( << "request update extent, update ext = "
250                  << PRINTEXTENT( ext ) << endl );
251 
252   for (int axis = 0; axis < 3; axis++)
253     {
254     int wholeMin = ext[axis*2];
255     int wholeMax = ext[axis*2+1];
256     int dimension = wholeMax - wholeMin + 1;
257 
258     // Scale the output extent
259     wholeMin = static_cast<int>(ceil(static_cast<double>(wholeMin / this->Magnification)));
260     wholeMax = dimension != 1? wholeMin + static_cast<int>(floor(static_cast<double>(dimension / this->Magnification))) -1:
261 
262     ext[axis*2] = wholeMin;
263     ext[axis*2+1] = wholeMax;
264     }
265   vtkDebugMacro( << "UPDATE_EXTENT: " << ext[0] << ", " << ext[1] << ", "
266                  << ext[2] << ", "    << ext[3] << ", " << ext[4] << ", "
267                  << ext[5] << endl );
268   inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), ext, 6);
269 
270   vtkDebugMacro( << "request update extent, update ext2 = "
271                  << PRINTEXTENT( ext ) << endl );
272 
273 
274   if(inputVector[1]!=0 && inputVector[1]->GetInformationObject(0) != NULL) // optional input
275     {
276     inInfo = inputVector[1]->GetInformationObject(0);
277     // always request the whole extent
278     inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(),
279                 inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()),
280                 6);
281     }
282 
283   return 1;
284 }
285 
286 //----------------------------------------------------------------------------
287 // Stolen from vtkImageAlgorithm. Should be in vtkStructuredGridAlgorithm.
AllocateOutputData(vtkDataObject * output,vtkInformation * outInfo)288 void vtkStructuredGridLIC2D::AllocateOutputData(vtkDataObject *output,
289                                                 vtkInformation *outInfo)
290 {
291   // set the extent to be the update extent
292   vtkStructuredGrid *out = vtkStructuredGrid::SafeDownCast(output);
293   if (out)
294     {
295     out->SetExtent(outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT()));
296     }
297   else
298     {
299     vtkImageData *out2 = vtkImageData::SafeDownCast(output);
300     if (out2)
301       {
302       out2->SetExtent(outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT()));
303       }
304     }
305 }
306 
307 //----------------------------------------------------------------------------
308 // Stolen from vtkImageData. Should be in vtkStructuredGrid.
AllocateScalars(vtkStructuredGrid * sg,vtkInformation * outInfo)309 void vtkStructuredGridLIC2D::AllocateScalars(vtkStructuredGrid *sg,
310                                              vtkInformation *outInfo)
311 {
312   int newType = VTK_DOUBLE;
313   int newNumComp = 1;
314 
315   vtkInformation *scalarInfo = vtkDataObject::GetActiveFieldInformation(
316     outInfo,
317     vtkDataObject::FIELD_ASSOCIATION_POINTS, vtkDataSetAttributes::SCALARS);
318   if (scalarInfo)
319     {
320     newType = scalarInfo->Get( vtkDataObject::FIELD_ARRAY_TYPE() );
321     if ( scalarInfo->Has(vtkDataObject::FIELD_NUMBER_OF_COMPONENTS()) )
322       {
323       newNumComp = scalarInfo->Get( vtkDataObject::FIELD_NUMBER_OF_COMPONENTS() );
324       }
325     }
326 
327   vtkDataArray *scalars;
328 
329   // if the scalar type has not been set then we have a problem
330   if (newType == VTK_VOID)
331     {
332     vtkErrorMacro("Attempt to allocate scalars before scalar type was set!.");
333     return;
334     }
335 
336   const int* extent = sg->GetExtent();
337   // Use vtkIdType to avoid overflow on large images
338   vtkIdType dims[3];
339   dims[0] = extent[1] - extent[0] + 1;
340   dims[1] = extent[3] - extent[2] + 1;
341   dims[2] = extent[5] - extent[4] + 1;
342   vtkIdType imageSize = dims[0]*dims[1]*dims[2];
343 
344   // if we currently have scalars then just adjust the size
345   scalars = sg->GetPointData()->GetScalars();
346   if (scalars && scalars->GetDataType() == newType
347       && scalars->GetReferenceCount() == 1)
348     {
349     scalars->SetNumberOfComponents(newNumComp);
350     scalars->SetNumberOfTuples(imageSize);
351     // Since the execute method will be modifying the scalars
352     // directly.
353     scalars->Modified();
354     return;
355     }
356 
357   // allocate the new scalars
358   scalars = vtkDataArray::CreateDataArray(newType);
359   scalars->SetNumberOfComponents(newNumComp);
360 
361   // allocate enough memory
362   scalars->SetNumberOfTuples(imageSize);
363 
364   sg->GetPointData()->SetScalars(scalars);
365   scalars->Delete();
366 }
367 
368 
369 //----------------------------------------------------------------------------
RequestData(vtkInformation * vtkNotUsed (request),vtkInformationVector ** inputVector,vtkInformationVector * outputVector)370 int vtkStructuredGridLIC2D::RequestData(
371   vtkInformation        * vtkNotUsed(request),
372   vtkInformationVector ** inputVector,
373   vtkInformationVector  * outputVector )
374 {
375   // 3 passes:
376   // pass 1: render to compute the transformed vector field for the points.
377   // pass 2: perform LIC with the new vector field. This has to happen in a
378   // different pass than computation of the transformed vector.
379   // pass 3: Render structured slice quads with correct texture correct
380   // tcoords and apply the LIC texture to it.
381 
382   vtkInformation    * inInfo = inputVector[0]->GetInformationObject(0);
383   vtkStructuredGrid * input  = vtkStructuredGrid::SafeDownCast
384                    (  inInfo->Get( vtkDataObject::DATA_OBJECT() )  );
385 
386   int inputRequestedExtent[6];
387   inInfo->Get(
388         vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(),
389         inputRequestedExtent);
390 
391   // Check if the input image is a 2D image (not 0D, not 1D, not 3D)
392   int dims[3];
393   vtkStructuredExtent::GetDimensions( inputRequestedExtent, dims );
394 
395   vtkDebugMacro( << "dims = " << dims[0] << " "
396                  << dims[1] << " " << dims[2] << endl );
397   vtkDebugMacro( << "requested ext = " << inputRequestedExtent[0] << " "
398                  << inputRequestedExtent[1] << " " << inputRequestedExtent[2]
399                  << " " << inputRequestedExtent[3] << " "
400                  << inputRequestedExtent[4] << " "
401                  << inputRequestedExtent[5] << endl );
402 
403   if(   !( (dims[0] == 1) && (dims[1] > 1) && (dims[2] > 1) )
404      && !( (dims[1] == 1) && (dims[0] > 1) && (dims[2] > 1) )
405      && !( (dims[2] == 1) && (dims[0] > 1) && (dims[1] > 1) )
406     )
407     {
408     vtkErrorMacro( << "input is not a 2D image." << endl );
409     input  = NULL;
410     inInfo = NULL;
411     return 0;
412     }
413   if( input->GetPointData() == 0 )
414     {
415     vtkErrorMacro( << "input does not have point data." );
416     input  = NULL;
417     inInfo = NULL;
418     return 0;
419     }
420   if( input->GetPointData()->GetVectors() == 0 )
421     {
422     vtkErrorMacro( << "input does not vectors on point data." );
423     input  = NULL;
424     inInfo = NULL;
425     return 0;
426     }
427 
428   if ( !this->Context )
429     {
430     vtkRenderWindow * renWin = vtkRenderWindow::New();
431     if (  this->SetContext( renWin ) == 0  )
432       {
433       vtkErrorMacro("Invalid render window");
434       renWin->Delete();
435       renWin = NULL;
436       input  = NULL;
437       inInfo = NULL;
438       return 0;
439       }
440 
441     renWin = NULL; // to be released via this->context
442     this->OwnWindow = true;
443     }
444 
445   vtkInformation    * outInfo = outputVector->GetInformationObject(0);
446   vtkStructuredGrid * output  = vtkStructuredGrid::SafeDownCast(
447     outInfo->Get(vtkDataObject::DATA_OBJECT()));
448   this->AllocateOutputData(output, outInfo);
449   output->ShallowCopy(input);
450 
451   vtkInformation * outInfoTexture = outputVector->GetInformationObject(1);
452   vtkImageData   * outputTexture  = vtkImageData::SafeDownCast(
453     outInfoTexture->Get(vtkDataObject::DATA_OBJECT()));
454   this->AllocateOutputData(outputTexture, outInfoTexture);
455 
456   // Noise.
457   vtkInformation *noiseInfo = inputVector[1]->GetInformationObject(0);
458   vtkImageData *noise = 0;
459   if (noiseInfo == 0)
460     {
461     this->NoiseSource->Update();
462     noise = this->NoiseSource->GetOutput();
463     }
464   else
465     {
466     noise = vtkImageData::SafeDownCast(
467       noiseInfo->Get(vtkDataObject::DATA_OBJECT()));
468 
469     if(noise->GetPointData()==0)
470       {
471       vtkErrorMacro(<<"provided noise does not have point data.");
472       return 0;
473       }
474     if(noise->GetPointData()->GetScalars()==0)
475       {
476       vtkErrorMacro(<<"provided noise does not have scalars on point data.");
477       return 0;
478       }
479     }
480 
481   vtkOpenGLClearErrorMacro();
482 
483   int width;
484   int height;
485   int firstComponent;
486   int secondComponent;
487   int slice;
488   if (dims[0] == 1)
489     {
490     vtkDebugMacro( << "x" << endl );
491     firstComponent = 1;
492     secondComponent = 2;
493     slice = 0;
494     }
495   else
496     {
497     if (dims[1] == 1)
498       {
499       vtkDebugMacro( << "y" << endl );
500       firstComponent = 0;
501       secondComponent = 2;
502       slice = 1;
503       }
504     else
505       {
506       vtkDebugMacro( << "z" << endl );
507       firstComponent = 0;
508       secondComponent = 1;
509       slice = 2;
510       }
511     }
512 
513   width = dims[firstComponent];
514   height = dims[secondComponent];
515 
516   vtkDebugMacro( << "w = " << width << " h = " << height << endl );
517 
518   vtkDataTransferHelper * vectorFieldBus = vtkDataTransferHelper::New();
519   vectorFieldBus->SetContext(this->Context);
520   vectorFieldBus->SetCPUExtent(inputRequestedExtent); // input->GetExtent());
521   vectorFieldBus->SetGPUExtent(inputRequestedExtent); // input->GetExtent());
522   //  vectorFieldBus->SetTextureExtent(input->GetExtent());
523   vectorFieldBus->SetArray(input->GetPointData()->GetVectors());
524 
525   vtkDataTransferHelper * pointBus = vtkDataTransferHelper::New();
526   pointBus->SetContext(this->Context);
527   pointBus->SetCPUExtent(inputRequestedExtent); // input->GetExtent());
528   pointBus->SetGPUExtent(inputRequestedExtent); // input->GetExtent());
529   //  pointBus->SetTextureExtent(input->GetExtent());
530   pointBus->SetArray(input->GetPoints()->GetData());
531 
532   vtkOpenGLExtensionManager * mgr = vtkOpenGLExtensionManager::New();
533   mgr->SetRenderWindow(this->Context);
534 
535   // Vector field in image space.
536   int magWidth = this->Magnification*width;
537   int magHeight = this->Magnification*height;
538 
539   vtkTextureObject * vector2 = vtkTextureObject::New();
540   vector2->SetContext(this->Context);
541   vector2->Create2D(magWidth,magHeight,3,VTK_FLOAT,false);
542 
543   vtkDebugMacro( << "Vector field in image space (target) textureId = "
544                  << vector2->GetHandle() << endl );
545 
546   vtkFrameBufferObject *fbo = vtkFrameBufferObject::New();
547   fbo->SetContext(this->Context);
548   fbo->SetColorBuffer(0,vector2);
549   fbo->SetNumberOfRenderTargets(1);
550   fbo->SetActiveBuffer(0);
551 
552   // TODO --
553   // step size is incorrect here
554   // guard pixels are needed for parallel operations
555 
556   if (  !fbo->Start( magWidth, magHeight, false )  )
557     {
558     mgr->Delete();
559     fbo->Delete();
560     vector2->Delete();
561     pointBus->Delete();
562     vectorFieldBus->Delete();
563 
564     mgr = NULL;
565     fbo = NULL;
566     vector2  = NULL;
567     pointBus = NULL;
568     vectorFieldBus   = NULL;
569 
570     noise   = NULL;
571     input   = NULL;
572     inInfo  = NULL;
573     output  = NULL;
574     outInfo = NULL;
575     noiseInfo = NULL;
576     outputTexture  = NULL;
577     outInfoTexture = NULL;
578 
579     this->FBOSuccess = 0;
580     return 0;
581     }
582   this->FBOSuccess = 1;
583 
584   vtkShaderProgram2 *pgm = vtkShaderProgram2::New();
585   pgm->SetContext(static_cast<vtkOpenGLRenderWindow *>(this->Context.GetPointer()));
586 
587   vtkShader2 *shader = vtkShader2::New();
588   shader->SetType(VTK_SHADER_TYPE_FRAGMENT);
589   shader->SetSourceCode(vtkStructuredGridLIC2D_fs);
590   shader->SetContext(pgm->GetContext());
591   pgm->GetShaders()->AddItem(shader);
592   shader->Delete();
593   shader = NULL;
594 
595   pgm->Build();
596   if(pgm->GetLastBuildStatus()!=VTK_SHADER_PROGRAM2_LINK_SUCCEEDED)
597     {
598     vtkErrorMacro("shader build error.");
599     return 0;
600     }
601 
602   int value = 0;
603   pgm->GetUniformVariables()->SetUniformi("texPoints",1,&value);
604   value = 1;
605   pgm->GetUniformVariables()->SetUniformi("texVectorField",1,&value);
606   float fvalues[3];
607   fvalues[0] = static_cast<float>(dims[0]);
608   fvalues[1] = static_cast<float>(dims[1]);
609   fvalues[2] = static_cast<float>(dims[2]);
610   pgm->GetUniformVariables()->SetUniformf("uDimensions",3,fvalues);
611   value = slice;
612   pgm->GetUniformVariables()->SetUniformi("uSlice",1,&slice);
613 
614   vtkgl::ActiveTexture(vtkgl::TEXTURE0);
615   pointBus->Upload(0,0);
616   vtkTextureObject *points = pointBus->GetTexture();
617   points->Bind();
618   glTexParameteri(points->GetTarget(),GL_TEXTURE_WRAP_S, GL_CLAMP);
619   glTexParameteri(points->GetTarget(),GL_TEXTURE_WRAP_T, GL_CLAMP);
620   glTexParameteri(points->GetTarget(), vtkgl::TEXTURE_WRAP_R, GL_CLAMP);
621   glTexParameteri(points->GetTarget(), GL_TEXTURE_MIN_FILTER, GL_NEAREST);
622   glTexParameteri(points->GetTarget(), GL_TEXTURE_MAG_FILTER, GL_NEAREST);
623 
624   vtkDebugMacro( << "points on texture unit 0, textureId == "
625                  << points->GetHandle() << endl );
626 
627   vtkgl::ActiveTexture(vtkgl::TEXTURE1);
628   vectorFieldBus->Upload(0,0);
629   vtkTextureObject *vectorField = vectorFieldBus->GetTexture();
630   vectorField->Bind();
631   glTexParameteri(vectorField->GetTarget(),GL_TEXTURE_WRAP_S, GL_CLAMP);
632   glTexParameteri(vectorField->GetTarget(),GL_TEXTURE_WRAP_T, GL_CLAMP);
633   glTexParameteri(vectorField->GetTarget(), vtkgl::TEXTURE_WRAP_R, GL_CLAMP);
634   glTexParameteri(vectorField->GetTarget(), GL_TEXTURE_MIN_FILTER, GL_NEAREST);
635   glTexParameteri(vectorField->GetTarget(), GL_TEXTURE_MAG_FILTER, GL_NEAREST);
636 
637   vtkDebugMacro( << "vector field on texture unit 1, textureId == "
638                  << vectorField->GetHandle() << endl );
639 
640   pgm->Use();
641   if(!pgm->IsValid())
642     {
643     vtkErrorMacro(<<" validation of the program failed: "<<pgm->GetLastValidateLog());
644     }
645   vtkOpenGLCheckErrorMacro("failed during config");
646 
647   vtkDebugMacro( << "glFinish before rendering quad" << endl );
648 
649   fbo->RenderQuad(0, magWidth-1,0, magHeight-1);
650   vtkOpenGLCheckErrorMacro("StructuredGridLIC2D projection fialed");
651 
652   vtkDebugMacro( << "glFinish after rendering quad" << endl );
653 
654   pgm->Restore();
655 
656   vtkLineIntegralConvolution2D *internal = vtkLineIntegralConvolution2D::New();
657   if (  !internal->IsSupported( this->Context )  )
658     {
659     pgm->ReleaseGraphicsResources();
660 
661     pgm->Delete();
662     mgr->Delete();
663     fbo->Delete();
664     vector2->Delete();
665     internal->Delete();
666     pointBus->Delete();
667     vectorFieldBus->Delete();
668 
669     pgm = NULL;
670     mgr = NULL;
671     fbo = NULL;
672     vector2  = NULL;
673     internal = NULL;
674     pointBus = NULL;
675     vectorFieldBus = NULL;
676 
677     noise   = NULL;
678     input   = NULL;
679     inInfo  = NULL;
680     points  = NULL;
681     output  = NULL;
682     outInfo = NULL;
683     noiseInfo   = NULL;
684     vectorField = NULL;
685     outputTexture  = NULL;
686     outInfoTexture = NULL;
687 
688     this->LICSuccess = 0;
689     return 0;
690     }
691 
692   internal->SetContext(this->Context);
693   internal->SetNumberOfSteps(this->Steps);
694   internal->SetStepSize(this->StepSize);
695   internal->SetComponentIds(firstComponent,secondComponent);
696 
697   vtkDataTransferHelper *noiseBus = vtkDataTransferHelper::New();
698   noiseBus->SetContext(this->Context);
699   noiseBus->SetCPUExtent(noise->GetExtent());
700   noiseBus->SetGPUExtent(noise->GetExtent());
701   //  noiseBus->SetTextureExtent(noise->GetExtent());
702   noiseBus->SetArray(noise->GetPointData()->GetScalars());
703   noiseBus->Upload(0,0);
704 
705   vtkTextureObject *licTex = internal->Execute(vector2, noiseBus->GetTexture());
706   if (licTex == NULL)
707     {
708     pgm->ReleaseGraphicsResources();
709 
710     pgm->Delete();
711     mgr->Delete();
712     fbo->Delete();
713     vector2->Delete();
714     internal->Delete();
715     pointBus->Delete();
716     noiseBus->Delete();
717     vectorFieldBus->Delete();
718 
719     pgm = NULL;
720     mgr = NULL;
721     fbo = NULL;
722     vector2 = NULL;
723     internal = NULL;
724     pointBus = NULL;
725     noiseBus = NULL;
726     vectorFieldBus = NULL;
727 
728     noise = NULL;
729     input = NULL;
730     inInfo = NULL;
731     points = NULL;
732     output = NULL;
733     outInfo = NULL;
734     noiseInfo = NULL;
735     vectorField = NULL;
736     outputTexture = NULL;
737     outInfoTexture = NULL;
738 
739     this->LICSuccess = 0;
740     return 0;
741     }
742   this->LICSuccess = 1;
743 
744   // transfer lic from texture to vtk array
745   vtkPixelExtent magLicExtent(magWidth, magHeight);
746   vtkIdType nOutTups = magLicExtent.Size();
747 
748   vtkFloatArray *licOut = vtkFloatArray::New();
749   licOut->SetNumberOfComponents(3);
750   licOut->SetNumberOfTuples(nOutTups);
751   licOut->SetName("LIC");
752 
753   vtkPixelBufferObject *licPBO = licTex->Download();
754 
755   vtkPixelTransfer::Blit<float,float>(
756         magLicExtent,
757         magLicExtent,
758         magLicExtent,
759         magLicExtent,
760         4,
761         (float*)licPBO->MapPackedBuffer(),
762         3,
763         licOut->GetPointer(0));
764 
765   licPBO->UnmapPackedBuffer();
766   licPBO->Delete();
767   licTex->Delete();
768 
769   // mask and convert to gray scale 3 components
770   float *pLicOut = licOut->GetPointer(0);
771   for (vtkIdType i=0; i<nOutTups; ++i)
772     {
773     float lic = pLicOut[3*i];
774     float mask = pLicOut[3*i+1];
775     if ( mask )
776       {
777       pLicOut[3*i+1] = pLicOut[3*i+2] = pLicOut[3*i] = 0.0f;
778       }
779     else
780       {
781       pLicOut[3*i+1] = pLicOut[3*i+2] = lic;
782       }
783     }
784 
785   outputTexture->GetPointData()->SetScalars(licOut);
786   licOut->Delete();
787 
788   // Pass three. Generate texture coordinates. Software.
789   vtkFloatArray *tcoords = vtkFloatArray::New();
790   tcoords->SetNumberOfComponents(2);
791   tcoords->SetNumberOfTuples(dims[0]*dims[1]*dims[2]);
792   output->GetPointData()->SetTCoords(tcoords);
793   tcoords->Delete();
794 
795   double ddim[3];
796   ddim[0] = static_cast<double>(dims[0]-1);
797   ddim[1] = static_cast<double>(dims[1]-1);
798   ddim[2] = static_cast<double>(dims[2]-1);
799 
800   int tz = 0;
801   while(tz < dims[slice])
802     {
803     int ty = 0;
804     while(ty < dims[secondComponent])
805       {
806       int tx = 0;
807       while(tx < dims[firstComponent])
808         {
809         tcoords->SetTuple2(
810               (tz*dims[secondComponent]+ty)*dims[firstComponent]+tx,
811               tx/ddim[firstComponent],
812               ty/ddim[secondComponent]);
813         ++tx;
814         }
815       ++ty;
816       }
817     ++tz;
818     }
819 
820   internal->Delete();
821   noiseBus->Delete();
822   vectorFieldBus->Delete();
823   pointBus->Delete();
824   mgr->Delete();
825   vector2->Delete();
826   fbo->Delete();
827   pgm->ReleaseGraphicsResources();
828   pgm->Delete();
829 
830   // Make sure the active texture is back to texture0 for the part of the
831   // pipeline using OpenGL 1.1 (texture on actor)
832   vtkgl::ActiveTexture(vtkgl::TEXTURE0);
833 
834   vtkOpenGLCheckErrorMacro("failed after RequestData");
835 
836   return 1;
837 }
838 
839 //----------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)840 void vtkStructuredGridLIC2D::PrintSelf( ostream & os, vtkIndent indent )
841 {
842   this->Superclass::PrintSelf( os, indent );
843 
844   os << indent << "Steps: " << this->Steps << "\n";
845   os << indent << "StepSize: " << this->StepSize << "\n";
846   os << indent << "FBOSuccess: " << this->FBOSuccess << "\n";
847   os << indent << "LICSuccess: " << this->LICSuccess << "\n";
848   os << indent << "Magnification: " << this->Magnification << "\n";
849   os << indent << "OpenGLExtensionsSupported: "
850                << this->OpenGLExtensionsSupported << "\n";
851 }
852