vtkVolume.cxx 20.8 KB
Newer Older
Ken Martin's avatar
Ken Martin committed
1 2 3 4 5
/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkVolume.cxx

6
  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7 8
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
Ken Martin's avatar
Ken Martin committed
9

10 11
     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12
     PURPOSE.  See the above copyright notice for more information.
Ken Martin's avatar
Ken Martin committed
13 14

=========================================================================*/
Ken Martin's avatar
Ken Martin committed
15
#include "vtkVolume.h"
16 17

#include "vtkCamera.h"
Andy Cedilnik's avatar
Andy Cedilnik committed
18
#include "vtkColorTransferFunction.h"
19
#include "vtkImageData.h"
20 21
#include "vtkLinearTransform.h"
#include "vtkMatrix4x4.h"
22
#include "vtkObjectFactory.h"
23
#include "vtkPiecewiseFunction.h"
24
#include "vtkPointData.h"
25
#include "vtkRenderer.h"
26
#include "vtkTransform.h"
27
#include "vtkVolumeCollection.h"
28
#include "vtkVolumeProperty.h"
29
#include "vtkAbstractVolumeMapper.h"
30

Brad King's avatar
Brad King committed
31
#include <math.h>
32

33
vtkCxxRevisionMacro(vtkVolume, "1.81");
Brad King's avatar
Brad King committed
34
vtkStandardNewMacro(vtkVolume);
Ken Martin's avatar
Ken Martin committed
35

Ken Martin's avatar
Ken Martin committed
36
// Creates a Volume with the following defaults: origin(0,0,0) 
37
// position=(0,0,0) scale=1 visibility=1 pickable=1 dragable=1
Ken Martin's avatar
Ken Martin committed
38
// orientation=(0,0,0).
Ken Martin's avatar
Ken Martin committed
39
vtkVolume::vtkVolume()
Ken Martin's avatar
Ken Martin committed
40
{
41
  this->Mapper                      = NULL;
42
  this->Property                    = NULL;
43 44 45 46 47 48 49 50 51
  
  for ( int i = 0; i < VTK_MAX_VRCOMP; i++ )
    {
    this->ScalarOpacityArray[i]          = NULL;
    this->RGBArray[i]                    = NULL;
    this->GrayArray[i]                   = NULL;
    this->CorrectedScalarOpacityArray[i] = NULL;
    }
  
52
  this->CorrectedStepSize           = -1;
53
  this->ArraySize                   =  0;
Ken Martin's avatar
Ken Martin committed
54 55
}

56 57
// Destruct a volume
vtkVolume::~vtkVolume()
Ken Martin's avatar
Ken Martin committed
58
{
59
  if (this->Property )
60
    {
61
    this->Property->UnRegister(this);
62
    }
63

64
  this->SetMapper(NULL);
65

66
  for ( int i = 0; i < VTK_MAX_VRCOMP; i++ )
Bill Lorensen's avatar
Bill Lorensen committed
67
    {
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
    if ( this->ScalarOpacityArray[i] )
      {
      delete [] this->ScalarOpacityArray[i];
      }
    
    if ( this->RGBArray[i] )
      {
      delete [] this->RGBArray[i];
      }
    
    if ( this->GrayArray[i] )
      {
      delete [] this->GrayArray[i];
      }
    
    if ( this->CorrectedScalarOpacityArray[i] )
      {
      delete [] this->CorrectedScalarOpacityArray[i];
      }
Bill Lorensen's avatar
Bill Lorensen committed
87
    }
Ken Martin's avatar
Ken Martin committed
88 89
}

90
void vtkVolume::GetVolumes(vtkPropCollection *vc)
Ken Martin's avatar
Ken Martin committed
91 92 93 94
{
  vc->AddItem(this);
}

95
// Shallow copy of an volume.
Will Schroeder's avatar
Will Schroeder committed
96
void vtkVolume::ShallowCopy(vtkProp *prop)
Ken Martin's avatar
Ken Martin committed
97
{
Will Schroeder's avatar
Will Schroeder committed
98
  vtkVolume *v = vtkVolume::SafeDownCast(prop);
Ken Martin's avatar
Ken Martin committed
99

Will Schroeder's avatar
Will Schroeder committed
100 101 102 103 104 105 106 107
  if ( v != NULL )
    {
    this->SetMapper(v->GetMapper());
    this->SetProperty(v->GetProperty());
    }

  // Now do superclass
  this->vtkProp3D::ShallowCopy(prop);
Ken Martin's avatar
Ken Martin committed
108 109
}

110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
float *vtkVolume::GetScalarOpacityArray(int index)
{
  if ( index < 0 || index >= VTK_MAX_VRCOMP )
    {
    vtkErrorMacro("Index out of range [0-" << VTK_MAX_VRCOMP << 
                  "]: " << index );
    return NULL;
    }
  return this->ScalarOpacityArray[index];
}

float *vtkVolume::GetCorrectedScalarOpacityArray(int index)
{
  if ( index < 0 || index >= VTK_MAX_VRCOMP )
    {
    vtkErrorMacro("Index out of range [0-" << VTK_MAX_VRCOMP << 
                  "]: " << index );
    return NULL;
    }
  return this->CorrectedScalarOpacityArray[index];
}

float *vtkVolume::GetGradientOpacityArray(int index)
{
  if ( index < 0 || index >= VTK_MAX_VRCOMP )
    {
    vtkErrorMacro("Index out of range [0-" << VTK_MAX_VRCOMP << 
                  "]: " << index );
    return NULL;
    }
  return this->GradientOpacityArray[index];
}

float vtkVolume::GetGradientOpacityConstant(int index)
{
  if ( index < 0 || index >= VTK_MAX_VRCOMP )
    {
    vtkErrorMacro("Index out of range [0-" << VTK_MAX_VRCOMP << 
                  "]: " << index );
149
    return 0;
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
    }
  return this->GradientOpacityConstant[index];
}

float *vtkVolume::GetGrayArray(int index)
{
  if ( index < 0 || index >= VTK_MAX_VRCOMP )
    {
    vtkErrorMacro("Index out of range [0-" << VTK_MAX_VRCOMP << 
                  "]: " << index );
    return NULL;
    }
  return this->GrayArray[index];
}

float *vtkVolume::GetRGBArray(int index)
{
  if ( index < 0 || index >= VTK_MAX_VRCOMP )
    {
    vtkErrorMacro("Index out of range [0-" << VTK_MAX_VRCOMP << 
                  "]: " << index );
    return NULL;
    }
  return this->RGBArray[index];
}

176
void vtkVolume::SetMapper(vtkAbstractVolumeMapper *mapper)
177
{
178
  if (this->Mapper != mapper)
179
    {
Ken Martin's avatar
Ken Martin committed
180 181 182 183 184
    if (this->Mapper != NULL) 
      { 
      this->Mapper->RemoveConsumer(this);
      this->Mapper->UnRegister(this); 
      }   
185
    this->Mapper = mapper;
Ken Martin's avatar
Ken Martin committed
186 187 188 189 190
    if (this->Mapper != NULL) 
      { 
      this->Mapper->Register(this); 
      this->Mapper->AddConsumer(this);
      }     
191 192 193 194
    this->Modified();
    }
}

195 196 197 198 199 200 201 202 203 204
float vtkVolume::ComputeScreenCoverage( vtkViewport *vp )
{
  float coverage = 1.0;
  
  vtkRenderer *ren = vtkRenderer::SafeDownCast( vp );
  
  if ( ren )
    {
    vtkCamera *cam = ren->GetActiveCamera();
    ren->ComputeAspect();
Ken Martin's avatar
Ken Martin committed
205 206 207
    double *aspect = ren->GetAspect();
    vtkMatrix4x4 *mat = cam->GetCompositePerspectiveTransformMatrix( 
      aspect[0]/aspect[1], 0.0, 1.0 );
Ken Martin's avatar
Ken Martin committed
208
    double *bounds = this->GetBounds();
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
    float minX =  1.0;
    float maxX = -1.0;
    float minY =  1.0;
    float maxY = -1.0;
    int i, j, k;
    float p[4];
    for ( k = 0; k < 2; k++ )
      {
      for ( j = 0; j < 2; j++ )
        {
        for ( i = 0; i < 2; i++ )
          {
          p[0] = bounds[i];
          p[1] = bounds[2+j];
          p[2] = bounds[4+k];
          p[3] = 1.0;
          mat->MultiplyPoint( p, p );
          if ( p[3] )
            {
            p[0] /= p[3];
            p[1] /= p[3];
            p[2] /= p[3];          
            }
          
          minX = (p[0] < minX)?(p[0]):(minX);
          minY = (p[1] < minY)?(p[1]):(minY);
          maxX = (p[0] > maxX)?(p[0]):(maxX);
          maxY = (p[1] > maxY)?(p[1]):(maxY);
          }
        }
      }
     
    coverage = (maxX-minX)*(maxY-minY)*.25;
    coverage = (coverage > 1.0 )?(1.0):(coverage);
    coverage = (coverage < 0.0 )?(0.0):(coverage);
    }
  
  
  return coverage;
}

Ken Martin's avatar
Ken Martin committed
250
// Get the bounds for this Volume as (Xmin,Xmax,Ymin,Ymax,Zmin,Zmax).
Ken Martin's avatar
Ken Martin committed
251
double *vtkVolume::GetBounds()
Ken Martin's avatar
Ken Martin committed
252 253
{
  int i,n;
Ken Martin's avatar
Ken Martin committed
254
  double *bounds, bbox[24], *fptr;
Ken Martin's avatar
Ken Martin committed
255
  
256
  // get the bounds of the Mapper if we have one
257
  if (!this->Mapper)
258 259 260 261
    {
    return this->Bounds;
    }

262
  bounds = this->Mapper->GetBounds();
Ken Martin's avatar
Ken Martin committed
263 264 265 266 267
  // Check for the special case when the mapper's bounds are unknown
  if (!bounds)
    {
    return bounds;
    }
268

Ken Martin's avatar
Ken Martin committed
269 270 271 272 273 274 275 276 277 278 279
  // fill out vertices of a bounding box
  bbox[ 0] = bounds[1]; bbox[ 1] = bounds[3]; bbox[ 2] = bounds[5];
  bbox[ 3] = bounds[1]; bbox[ 4] = bounds[2]; bbox[ 5] = bounds[5];
  bbox[ 6] = bounds[0]; bbox[ 7] = bounds[2]; bbox[ 8] = bounds[5];
  bbox[ 9] = bounds[0]; bbox[10] = bounds[3]; bbox[11] = bounds[5];
  bbox[12] = bounds[1]; bbox[13] = bounds[3]; bbox[14] = bounds[4];
  bbox[15] = bounds[1]; bbox[16] = bounds[2]; bbox[17] = bounds[4];
  bbox[18] = bounds[0]; bbox[19] = bounds[2]; bbox[20] = bounds[4];
  bbox[21] = bounds[0]; bbox[22] = bounds[3]; bbox[23] = bounds[4];
  
  // save the old transform
280
  this->Transform->Push();
281
  this->Transform->SetMatrix(this->GetMatrix());
Ken Martin's avatar
Ken Martin committed
282

283
  // and transform into actors coordinates
Ken Martin's avatar
Ken Martin committed
284 285 286
  fptr = bbox;
  for (n = 0; n < 8; n++) 
    {
287
    this->Transform->TransformPoint(fptr,fptr);
Ken Martin's avatar
Ken Martin committed
288 289 290
    fptr += 3;
    }
  
291
  this->Transform->Pop();  
Ken Martin's avatar
Ken Martin committed
292 293
  
  // now calc the new bounds
Ken Martin's avatar
Ken Martin committed
294 295
  this->Bounds[0] = this->Bounds[2] = this->Bounds[4] = VTK_DOUBLE_MAX;
  this->Bounds[1] = this->Bounds[3] = this->Bounds[5] = -VTK_DOUBLE_MAX;
Ken Martin's avatar
Ken Martin committed
296 297 298 299
  for (i = 0; i < 8; i++)
    {
    for (n = 0; n < 3; n++)
      {
Bill Lorensen's avatar
Bill Lorensen committed
300
      if (bbox[i*3+n] < this->Bounds[n*2])
301 302 303
        {
        this->Bounds[n*2] = bbox[i*3+n];
        }
Bill Lorensen's avatar
Bill Lorensen committed
304
      if (bbox[i*3+n] > this->Bounds[n*2+1])
305 306 307
        {
        this->Bounds[n*2+1] = bbox[i*3+n];
        }
Ken Martin's avatar
Ken Martin committed
308 309 310 311 312 313
      }
    }

  return this->Bounds;
}

314
// Get the minimum X bound
Ken Martin's avatar
Ken Martin committed
315
double vtkVolume::GetMinXBound( )
Ken Martin's avatar
Ken Martin committed
316 317
{
  this->GetBounds();
318 319 320 321
  return this->Bounds[0];
}

// Get the maximum X bound
Ken Martin's avatar
Ken Martin committed
322
double vtkVolume::GetMaxXBound( )
323 324 325 326 327 328
{
  this->GetBounds();
  return this->Bounds[1];
}

// Get the minimum Y bound
Ken Martin's avatar
Ken Martin committed
329
double vtkVolume::GetMinYBound( )
330 331 332
{
  this->GetBounds();
  return this->Bounds[2];
Ken Martin's avatar
Ken Martin committed
333 334
}

335
// Get the maximum Y bound
Ken Martin's avatar
Ken Martin committed
336
double vtkVolume::GetMaxYBound( )
Ken Martin's avatar
Ken Martin committed
337 338
{
  this->GetBounds();
339
  return this->Bounds[3];
Ken Martin's avatar
Ken Martin committed
340 341
}

342
// Get the minimum Z bound
Ken Martin's avatar
Ken Martin committed
343
double vtkVolume::GetMinZBound( )
Ken Martin's avatar
Ken Martin committed
344 345
{
  this->GetBounds();
346 347 348 349
  return this->Bounds[4];
}

// Get the maximum Z bound
Ken Martin's avatar
Ken Martin committed
350
double vtkVolume::GetMaxZBound( )
351 352 353 354 355
{
  this->GetBounds();
  return this->Bounds[5];
}

356 357 358 359 360 361 362
// If the volume mapper is of type VTK_FRAMEBUFFER_VOLUME_MAPPER, then
// this is its opportunity to render
int vtkVolume::RenderTranslucentGeometry( vtkViewport *vp )
{
  this->Update();

  if ( !this->Mapper )
Bill Lorensen's avatar
Bill Lorensen committed
363
    {
364 365
    vtkErrorMacro( << "You must specify a mapper!\n" );
    return 0;
Bill Lorensen's avatar
Bill Lorensen committed
366
    }
367

368
  // If we don't have any input return silently
369
  if ( !this->Mapper->GetDataSetInput() )
370 371 372 373
    {
    return 0;
    }
  
374 375
  // Force the creation of a property
  if( !this->Property )
376
    {
377
    this->GetProperty();
378
    }
379 380 381 382 383 384 385

  if( !this->Property )
    {
    vtkErrorMacro( << "Error generating a property!\n" );
    return 0;
    }

386 387
  this->Mapper->Render( (vtkRenderer *)vp, this );
  this->EstimatedRenderTime += this->Mapper->GetTimeToDraw();
388 389 390 391

  return 1;
}

392

393
void vtkVolume::ReleaseGraphicsResources(vtkWindow *win)
394 395
{
  // pass this information onto the mapper
396
  if (this->Mapper)
397
    {
398
    this->Mapper->ReleaseGraphicsResources(win);
399 400 401
    }
}

402 403
void vtkVolume::Update()
{
404
  if ( this->Mapper )
Bill Lorensen's avatar
Bill Lorensen committed
405
    {
406
    this->Mapper->Update();
Bill Lorensen's avatar
Bill Lorensen committed
407
    }
Ken Martin's avatar
Ken Martin committed
408 409
}

410
void vtkVolume::SetProperty(vtkVolumeProperty *property)
411
{
412
  if( this->Property != property )
413
    {
414 415 416
    if (this->Property != NULL) {this->Property->UnRegister(this);}
    this->Property = property;
    if (this->Property != NULL) 
417
      {
418 419
      this->Property->Register(this);
      this->Property->UpdateMTimes();
420
      }
421 422 423 424
    this->Modified();
    }
}

425
vtkVolumeProperty *vtkVolume::GetProperty()
426
{
427
  if( this->Property == NULL )
428
    {
429 430 431
    this->Property = vtkVolumeProperty::New();
    this->Property->Register(this);
    this->Property->Delete();
432
    }
433
  return this->Property;
434 435 436 437 438 439 440
}

unsigned long int vtkVolume::GetMTime()
{
  unsigned long mTime=this->vtkObject::GetMTime();
  unsigned long time;

441
  if ( this->Property != NULL )
442
    {
443
    time = this->Property->GetMTime();
444 445 446
    mTime = ( time > mTime ? time : mTime );
    }

447 448 449 450 451 452
  if ( this->UserMatrix != NULL )
    {
    time = this->UserMatrix->GetMTime();
    mTime = ( time > mTime ? time : mTime );
    }

453 454 455 456 457 458
  if ( this->UserTransform != NULL )
    {
    time = this->UserTransform->GetMTime();
    mTime = ( time > mTime ? time : mTime );
    }

459 460 461
  return mTime;
}

462 463 464 465 466
unsigned long int vtkVolume::GetRedrawMTime()
{
  unsigned long mTime=this->GetMTime();
  unsigned long time;

467
  if ( this->Mapper != NULL )
468
    {
469
    time = this->Mapper->GetMTime();
470
    mTime = ( time > mTime ? time : mTime );
471
    if (this->GetMapper()->GetDataSetInput() != NULL)
472
      {
473 474
      this->GetMapper()->GetDataSetInput()->Update();
      time = this->Mapper->GetDataSetInput()->GetMTime();
475 476 477
      mTime = ( time > mTime ? time : mTime );
      }
    }
478
  
479 480 481 482
  if ( this->Property != NULL )
    {
    time = this->Property->GetMTime();
    mTime = ( time > mTime ? time : mTime );
483
    
484 485
    int numComponents;
    
486 487 488
    if ( this->Mapper && this->Mapper->GetDataSetInput() &&
         this->Mapper->GetDataSetInput()->GetPointData() &&
         this->Mapper->GetDataSetInput()->GetPointData()->GetScalars() )
489
      {
490
      numComponents = this->Mapper->GetDataSetInput()->GetPointData()->
491 492 493 494 495 496 497 498
        GetScalars()->GetNumberOfComponents();
      }
    else
      {
      numComponents = 0;
      }
    
    for ( int i = 0; i < numComponents; i++ )
499
      {
500 501 502 503 504 505 506 507 508 509 510 511 512 513
      // Check the color transfer function (gray or rgb)
      if ( this->Property->GetColorChannels(i) == 1 )
        {
        time = this->Property->GetGrayTransferFunction(i)->GetMTime();
        mTime = ( time > mTime ? time : mTime );
        }
      else
        {
        time = this->Property->GetRGBTransferFunction(i)->GetMTime();
        mTime = ( time > mTime ? time : mTime );
        }
      
      // check the scalar opacity function
      time = this->Property->GetScalarOpacity(i)->GetMTime();
514
      mTime = ( time > mTime ? time : mTime );
515 516 517

      // check the gradient opacity function
      time = this->Property->GetGradientOpacity(i)->GetMTime();
518 519 520 521
      mTime = ( time > mTime ? time : mTime );
      }
    }

522 523 524
  return mTime;
}

525
void vtkVolume::UpdateTransferFunctions( vtkRenderer *vtkNotUsed(ren) )
526
{
527 528 529 530 531 532
  int                        dataType;
  vtkPiecewiseFunction      *sotf;
  vtkPiecewiseFunction      *gotf;
  vtkPiecewiseFunction      *graytf;
  vtkColorTransferFunction  *rgbtf;
  int                        colorChannels;
Andy Cedilnik's avatar
Andy Cedilnik committed
533
  
534
  int                        arraySize;
535 536
  
  // Check that we have scalars
537
  if ( this->Mapper == NULL ||
538 539 540
       this->Mapper->GetDataSetInput() == NULL ||
       this->Mapper->GetDataSetInput()->GetPointData() == NULL ||
       this->Mapper->GetDataSetInput()->GetPointData()->GetScalars() == NULL )
541
    {
542 543 544 545
    vtkErrorMacro(<<"Need scalar data to volume render");
    return;
    }
    
546
  // What is the type of the data?
547
  dataType = this->Mapper->GetDataSetInput()->
548
    GetPointData()->GetScalars()->GetDataType();
549 550
  
  if (dataType == VTK_UNSIGNED_CHAR)
551
    {
552
    arraySize = 256;
553
    }
554
  else if (dataType == VTK_UNSIGNED_SHORT)
555
    {
556
    arraySize = 65536;
557
    }
558
  else
559
    {
560
    vtkErrorMacro("Unsupported data type");
561 562 563
    return;
    }
  
564
  int numComponents = this->Mapper->GetDataSetInput()->GetPointData()->
565 566 567
    GetScalars()->GetNumberOfComponents();

  for ( int c = 0; c < numComponents; c++ )
568
    {
569 570 571 572 573 574 575
    
    // Did our array size change? If so, free up all our previous arrays
    // and create new ones for the scalar opacity and corrected scalar
    // opacity
    if ( arraySize != this->ArraySize )
      {
      if ( this->ScalarOpacityArray[c] )
576
        {
577
        delete [] this->ScalarOpacityArray[c];
578
        }
579
      if ( this->CorrectedScalarOpacityArray[c] )
580
        {
581
        delete [] this->CorrectedScalarOpacityArray[c];
582
        }
583
      if ( this->GrayArray[c] )
584
        {
585
        delete [] this->GrayArray[c];
586
        }
587
      if ( this->RGBArray[c] )
588
        {
589
        delete [] this->RGBArray[c];
590
        }
591 592 593 594 595 596 597 598
      
      // Allocate these two because we know we need them
      this->ScalarOpacityArray[c] = new float[arraySize];
      this->CorrectedScalarOpacityArray[c] = new float[arraySize];
      
      // Set these two to null - we will create one of them later
      this->GrayArray[c] = NULL;
      this->RGBArray[c] = NULL;
599
    }
600 601 602
  
    // How many color channels for this component?
    colorChannels = this->Property->GetColorChannels(c);
603
    
604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624
    // If we have 1 color channel and no gray array, create it.
    // Free the rgb array if there is one.
    if ( colorChannels == 1 && !this->GrayArray[c] )
      {
      if ( this->RGBArray[c] )
        {
        delete [] this->RGBArray[c];
        }              
      this->GrayArray[c] = new float[arraySize];
      }
    
    // If we have 3 color channels and no rgb array, create it.
    // Free the gray array if there is one.
    if ( colorChannels == 3 && !this->RGBArray[c] )
      {
      if ( this->GrayArray[c] )
        {
        delete [] this->GrayArray[c];
        }
      this->RGBArray[c] = new float[3*arraySize];
      }
625
    
626 627 628 629 630
    // Get the various functions for this index. There is no chance of
    // these being NULL since the property will create them if they were
    // not defined
    sotf          = this->Property->GetScalarOpacity(c);
    gotf          = this->Property->GetGradientOpacity(c);
631
    
632
    if ( colorChannels == 1 )
633
      {
634 635
      rgbtf         = NULL;
      graytf        = this->Property->GetGrayTransferFunction(c);
636 637 638
      }
    else
      {
639 640
      rgbtf         = this->Property->GetRGBTransferFunction(c);
      graytf        = NULL;
641
      }
642
    
643

644 645 646 647 648
    // Update the scalar opacity array if necessary
    if ( sotf->GetMTime() >
         this->ScalarOpacityArrayMTime[c] ||
         this->Property->GetScalarOpacityMTime(c) >
         this->ScalarOpacityArrayMTime[c] )
649
      {
Ken Martin's avatar
Ken Martin committed
650
      sotf->GetTable( 0.0, static_cast<double>(arraySize-1),  
651 652
                      arraySize, this->ScalarOpacityArray[c] );
      this->ScalarOpacityArrayMTime[c].Modified();
653
      }
654 655 656 657 658 659
    
    // Update the gradient opacity array if necessary
    if ( gotf->GetMTime() >
         this->GradientOpacityArrayMTime[c] ||
         this->Property->GetGradientOpacityMTime(c) >
         this->GradientOpacityArrayMTime[c] )
660
      {
661 662 663 664 665 666 667 668 669 670 671 672
      // Get values according to scale/bias from mapper 256 values are
      // in the table, the scale / bias values control what those 256 values
      // mean. 
      float scale = this->Mapper->GetGradientMagnitudeScale(c);
      float bias  = this->Mapper->GetGradientMagnitudeBias(c);
      
      float low   = -bias;
      float high  = 255 / scale - bias;
      
      gotf->GetTable( low, high, (int)(0x100), this->GradientOpacityArray[c] );
      
      if ( !strcmp(gotf->GetType(), "Constant") )
673
        {
674
        this->GradientOpacityConstant[c] = this->GradientOpacityArray[c][0];
675
        }
676
      else
677
        {
678
        this->GradientOpacityConstant[c] = -1.0;
679
        }
680
      
681
      this->GradientOpacityArrayMTime[c].Modified();
682
      }
683 684 685
    
    // Update the RGB or Gray transfer function if necessary
    if ( colorChannels == 1 )
686
      {
687 688 689 690
      if ( graytf->GetMTime() >
           this->GrayArrayMTime[c] ||
           this->Property->GetGrayTransferFunctionMTime(c) >
           this->GrayArrayMTime[c] )
691
        {
692 693 694
        graytf->GetTable( 0.0, static_cast<float>(arraySize-1),
                          arraySize, this->GrayArray[c] );
        this->GrayArrayMTime[c].Modified();
695
        }
696
      }
697
    else
698
      {
699 700 701 702
      if ( rgbtf->GetMTime() >
           this->RGBArrayMTime[c] ||
           this->Property->GetRGBTransferFunctionMTime(c) >
           this->RGBArrayMTime[c] )
703
        {
704 705 706
        rgbtf->GetTable( 0.0, static_cast<float>(arraySize-1),
                         arraySize, this->RGBArray[c] );
        this->RGBArrayMTime[c].Modified();
707
        }
Bill Lorensen's avatar
Bill Lorensen committed
708
      }
709
    }
710 711 712
  
  // reset the array size to the current size
  this->ArraySize = arraySize;
713 714
}

715 716 717
// This method computes the corrected alpha blending for a given
// step size.  The ScalarOpacityArray reflects step size 1.
// The CorrectedScalarOpacityArray reflects step size CorrectedStepSize.
718
void vtkVolume::UpdateScalarOpacityforSampleSize( vtkRenderer *vtkNotUsed(ren),
719
                                                  float sample_distance )
720 721 722 723 724
{
  int i;
  int needsRecomputing;
  float originalAlpha,correctedAlpha;
  float ray_scale;
725

726
  ray_scale = sample_distance;
727 728 729 730 731 732 733 734

  // step size changed
  needsRecomputing =  
      this->CorrectedStepSize-ray_scale >  0.0001;
  
  needsRecomputing = needsRecomputing || 
      this->CorrectedStepSize-ray_scale < -0.0001;

735 736
  // Check that we have scalars
  if ( this->Mapper == NULL ||
737 738 739
       this->Mapper->GetDataSetInput() == NULL ||
       this->Mapper->GetDataSetInput()->GetPointData() == NULL ||
       this->Mapper->GetDataSetInput()->GetPointData()->GetScalars() == NULL )
740 741 742 743 744
    {
    vtkErrorMacro(<<"Need scalar data to volume render");
    return;
    }

745
  int numComponents = this->Mapper->GetDataSetInput()->GetPointData()->
746 747 748
    GetScalars()->GetNumberOfComponents();

  if ( needsRecomputing )
749
    {
750
    this->CorrectedStepSize = ray_scale;
751
    }
752 753
  
  for ( int c = 0; c < numComponents; c++ )
754
    {
755 756 757
    if (needsRecomputing || 
        this->ScalarOpacityArrayMTime[c] > 
        this->CorrectedScalarOpacityArrayMTime[c])
758
      {
759
      this->CorrectedScalarOpacityArrayMTime[c].Modified();
760

761
      for (i = 0; i < this->ArraySize; i++)
762
        {
763 764 765 766 767 768 769 770 771 772 773 774 775 776
        originalAlpha = *(this->ScalarOpacityArray[c]+i);

        // this test is to accelerate the Transfer function correction
        if (originalAlpha > 0.0001)
          {
          correctedAlpha = 
            1.0-pow((double)(1.0-originalAlpha),
                    double(this->CorrectedStepSize));
          }
        else
          {
          correctedAlpha = originalAlpha;
          }
        *(this->CorrectedScalarOpacityArray[c]+i) = correctedAlpha;
777
        }
778 779 780
      }
    }
}
781 782


783
void vtkVolume::PrintSelf(ostream& os, vtkIndent indent)
Ken Martin's avatar
Ken Martin committed
784
{
Brad King's avatar
Brad King committed
785
  this->Superclass::PrintSelf(os,indent);
Ken Martin's avatar
Ken Martin committed
786

787
  if( this->Property )
788
    {
789 790
    os << indent << "Property:\n";
    this->Property->PrintSelf(os,indent.GetNextIndent());
791 792 793
    }
  else
    {
794
    os << indent << "Property: (not defined)\n";
795 796
    }

Lisa Avila's avatar
Lisa Avila committed
797 798 799 800 801 802 803 804 805 806
  if( this->Mapper )
    {
    os << indent << "Mapper:\n";
    this->Mapper->PrintSelf(os,indent.GetNextIndent());
    }
  else
    {
    os << indent << "Mapper: (not defined)\n";
    }

Ken Martin's avatar
Ken Martin committed
807
  // make sure our bounds are up to date
808
  if ( this->Mapper )
Ken Martin's avatar
Ken Martin committed
809
    {
810 811
      this->GetBounds();
      os << indent << "Bounds: (" << this->Bounds[0] << ", " 
812 813 814
         << this->Bounds[1] << ") (" << this->Bounds[2] << ") ("
         << this->Bounds[3] << ") (" << this->Bounds[4] << ") ("
         << this->Bounds[5] << ")\n";
Ken Martin's avatar
Ken Martin committed
815 816 817
    }
  else
    {
818
    os << indent << "Bounds: (not defined)\n";
Ken Martin's avatar
Ken Martin committed
819 820 821
    }
}