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