You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
304 lines
8.9 KiB
304 lines
8.9 KiB
/*=========================================================================
|
|
|
|
Program: Visualization Toolkit
|
|
Module: $RCSfile: vtkVolumeTextureMapper.cxx,v $
|
|
|
|
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
|
|
All rights reserved.
|
|
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
|
|
|
|
This software is distributed WITHOUT ANY WARRANTY; without even
|
|
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
PURPOSE. See the above copyright notice for more information.
|
|
|
|
=========================================================================*/
|
|
#include "vtkVolumeTextureMapper.h"
|
|
|
|
#include "vtkEncodedGradientShader.h"
|
|
#include "vtkFiniteDifferenceGradientEstimator.h"
|
|
#include "vtkGarbageCollector.h"
|
|
#include "vtkImageData.h"
|
|
#include "vtkPointData.h"
|
|
#include "vtkRenderer.h"
|
|
#include "vtkVolume.h"
|
|
#include "vtkVolumeProperty.h"
|
|
|
|
vtkCxxRevisionMacro(vtkVolumeTextureMapper, "$Revision: 1.2 $");
|
|
|
|
vtkVolumeTextureMapper::vtkVolumeTextureMapper()
|
|
{
|
|
this->GradientOpacityArray = NULL;
|
|
this->RGBAArray = NULL;
|
|
this->ArraySize = -1;
|
|
this->SampleDistance = 1.0;
|
|
this->GradientEstimator = vtkFiniteDifferenceGradientEstimator::New();
|
|
this->GradientShader = vtkEncodedGradientShader::New();
|
|
this->NumberOfComponents = 1;
|
|
}
|
|
|
|
vtkVolumeTextureMapper::~vtkVolumeTextureMapper()
|
|
{
|
|
this->SetGradientEstimator( NULL );
|
|
this->GradientShader->Delete();
|
|
|
|
if ( this->RGBAArray )
|
|
{
|
|
delete [] this->RGBAArray;
|
|
}
|
|
|
|
if ( this->GradientOpacityArray )
|
|
{
|
|
delete [] this->GradientOpacityArray;
|
|
}
|
|
}
|
|
|
|
void vtkVolumeTextureMapper::SetGradientEstimator(
|
|
vtkEncodedGradientEstimator *gradest )
|
|
{
|
|
|
|
// If we are setting it to its current value, don't do anything
|
|
if ( this->GradientEstimator == gradest )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// If we already have a gradient estimator, unregister it.
|
|
if ( this->GradientEstimator )
|
|
{
|
|
this->GradientEstimator->UnRegister(this);
|
|
this->GradientEstimator = NULL;
|
|
}
|
|
|
|
// If we are passing in a non-NULL estimator, register it
|
|
if ( gradest )
|
|
{
|
|
gradest->Register( this );
|
|
}
|
|
|
|
// Actually set the estimator, and consider the object Modified
|
|
this->GradientEstimator = gradest;
|
|
this->Modified();
|
|
}
|
|
|
|
void vtkVolumeTextureMapper::Update()
|
|
{
|
|
if ( this->GetInput() )
|
|
{
|
|
this->GetInput()->UpdateInformation();
|
|
this->GetInput()->SetUpdateExtentToWholeExtent();
|
|
this->GetInput()->Update();
|
|
}
|
|
}
|
|
|
|
void vtkVolumeTextureMapper::InitializeRender( vtkRenderer *ren,
|
|
vtkVolume *vol )
|
|
{
|
|
int size, i, j, k;
|
|
float *AArray;
|
|
float *RGBArray;
|
|
float *GArray;
|
|
int colorChannels;
|
|
float gradientOpacityConstant;
|
|
|
|
// Hang on to the render window - we'll need it to test for abort
|
|
this->RenderWindow = ren->GetRenderWindow();
|
|
|
|
vol->UpdateTransferFunctions( ren );
|
|
|
|
vol->UpdateScalarOpacityforSampleSize( ren, this->SampleDistance );
|
|
|
|
size = (int) vol->GetArraySize();
|
|
|
|
int numComponents = this->GetInput()->
|
|
GetPointData()->GetScalars()->GetNumberOfComponents();
|
|
|
|
if ( this->ArraySize != size ||
|
|
this->NumberOfComponents != numComponents )
|
|
{
|
|
if ( this->RGBAArray )
|
|
{
|
|
delete [] this->RGBAArray;
|
|
}
|
|
if ( this->GradientOpacityArray )
|
|
{
|
|
delete [] this->GradientOpacityArray;
|
|
}
|
|
|
|
this->RGBAArray = new unsigned char [4*size*numComponents];
|
|
this->GradientOpacityArray = new float [256*numComponents];
|
|
this->ArraySize = size;
|
|
this->NumberOfComponents = numComponents;
|
|
}
|
|
|
|
float *goPtr;
|
|
float *goArray;
|
|
|
|
for ( int c = 0; c < numComponents; c++ )
|
|
{
|
|
goPtr = vol->GetGradientOpacityArray(c);
|
|
goArray = this->GradientOpacityArray + c;
|
|
|
|
for ( i = 0; i < 256; i++ )
|
|
{
|
|
*(goArray) = *(goPtr++);
|
|
goArray += numComponents;
|
|
}
|
|
|
|
AArray = vol->GetCorrectedScalarOpacityArray(c);
|
|
colorChannels = vol->GetProperty()->GetColorChannels(c);
|
|
|
|
|
|
// Being less than 0.0 implies a transfer function, so just multiply by
|
|
// 1.0 here since the transfer function will supply the true opacity
|
|
// modulation value
|
|
gradientOpacityConstant = vol->GetGradientOpacityConstant(c);
|
|
if ( gradientOpacityConstant <= 0.0 )
|
|
{
|
|
gradientOpacityConstant = 1.0;
|
|
}
|
|
|
|
if ( colorChannels == 3 )
|
|
{
|
|
RGBArray = vol->GetRGBArray(c);
|
|
for ( i=0, j=(c*4), k=0; i < size; i++ )
|
|
{
|
|
this->RGBAArray[j++] = (unsigned char) (0.5 + (RGBArray[k++]*255.0));
|
|
this->RGBAArray[j++] = (unsigned char) (0.5 + (RGBArray[k++]*255.0));
|
|
this->RGBAArray[j++] = (unsigned char) (0.5 + (RGBArray[k++]*255.0));
|
|
this->RGBAArray[j++] =
|
|
(unsigned char) (0.5 + AArray[i]*255.0*gradientOpacityConstant);
|
|
|
|
j += 4*(numComponents-1);
|
|
}
|
|
}
|
|
else if ( colorChannels == 1 )
|
|
{
|
|
GArray = vol->GetGrayArray(c);
|
|
for ( i=0, j=(c*4); i < size; i++ )
|
|
{
|
|
this->RGBAArray[j++] = (unsigned char) (0.5 + (GArray[i]*255.0));
|
|
this->RGBAArray[j++] = (unsigned char) (0.5 + (GArray[i]*255.0));
|
|
this->RGBAArray[j++] = (unsigned char) (0.5 + (GArray[i]*255.0));
|
|
this->RGBAArray[j++] =
|
|
(unsigned char) (0.5 + AArray[i]*255.0*gradientOpacityConstant);
|
|
|
|
j += 4*(numComponents-1);
|
|
}
|
|
}
|
|
}
|
|
|
|
this->Shade = vol->GetProperty()->GetShade();
|
|
|
|
this->GradientEstimator->SetInput( this->GetInput() );
|
|
|
|
if ( this->Shade )
|
|
{
|
|
this->GradientShader->UpdateShadingTable( ren, vol,
|
|
this->GradientEstimator );
|
|
this->EncodedNormals =
|
|
this->GradientEstimator->GetEncodedNormals();
|
|
|
|
this->RedDiffuseShadingTable =
|
|
this->GradientShader->GetRedDiffuseShadingTable(vol);
|
|
this->GreenDiffuseShadingTable =
|
|
this->GradientShader->GetGreenDiffuseShadingTable(vol);
|
|
this->BlueDiffuseShadingTable =
|
|
this->GradientShader->GetBlueDiffuseShadingTable(vol);
|
|
|
|
this->RedSpecularShadingTable =
|
|
this->GradientShader->GetRedSpecularShadingTable(vol);
|
|
this->GreenSpecularShadingTable =
|
|
this->GradientShader->GetGreenSpecularShadingTable(vol);
|
|
this->BlueSpecularShadingTable =
|
|
this->GradientShader->GetBlueSpecularShadingTable(vol);
|
|
}
|
|
else
|
|
{
|
|
this->EncodedNormals = NULL;
|
|
this->RedDiffuseShadingTable = NULL;
|
|
this->GreenDiffuseShadingTable = NULL;
|
|
this->BlueDiffuseShadingTable = NULL;
|
|
this->RedSpecularShadingTable = NULL;
|
|
this->GreenSpecularShadingTable = NULL;
|
|
this->BlueSpecularShadingTable = NULL;
|
|
}
|
|
|
|
// If we have non-constant opacity on the gradient magnitudes,
|
|
// we need to use the gradient magnitudes to look up the opacity
|
|
if ( vol->GetGradientOpacityConstant() == -1.0 )
|
|
{
|
|
this->GradientMagnitudes =
|
|
this->GradientEstimator->GetGradientMagnitudes();
|
|
}
|
|
else
|
|
{
|
|
this->GradientMagnitudes = NULL;
|
|
}
|
|
|
|
this->GetInput()->GetOrigin( this->DataOrigin );
|
|
this->GetInput()->GetSpacing( this->DataSpacing );
|
|
|
|
this->ConvertCroppingRegionPlanesToVoxels();
|
|
}
|
|
|
|
float vtkVolumeTextureMapper::GetGradientMagnitudeScale()
|
|
{
|
|
if ( !this->GradientEstimator )
|
|
{
|
|
vtkErrorMacro( "You must have a gradient estimator set to get the scale" );
|
|
return 1.0;
|
|
}
|
|
|
|
return this->GradientEstimator->GetGradientMagnitudeScale();
|
|
}
|
|
|
|
float vtkVolumeTextureMapper::GetGradientMagnitudeBias()
|
|
{
|
|
if ( !this->GradientEstimator )
|
|
{
|
|
vtkErrorMacro( "You must have a gradient estimator set to get the bias" );
|
|
return 1.0;
|
|
}
|
|
|
|
return this->GradientEstimator->GetGradientMagnitudeBias();
|
|
}
|
|
|
|
// Print the vtkVolumeTextureMapper
|
|
void vtkVolumeTextureMapper::PrintSelf(ostream& os, vtkIndent indent)
|
|
{
|
|
this->Superclass::PrintSelf(os,indent);
|
|
|
|
if ( this->GradientEstimator )
|
|
{
|
|
os << indent << "Gradient Estimator: " << (this->GradientEstimator) <<
|
|
endl;
|
|
}
|
|
else
|
|
{
|
|
os << indent << "Gradient Estimator: (none)" << endl;
|
|
}
|
|
|
|
if ( this->GradientShader )
|
|
{
|
|
os << indent << "Gradient Shader: " << (this->GradientShader) << endl;
|
|
}
|
|
else
|
|
{
|
|
os << indent << "Gradient Shader: (none)" << endl;
|
|
}
|
|
|
|
// this->Shade is a temporary variable that should not be printed
|
|
// this->RenderWindow is a temporary variable that should not be printed
|
|
// this->DataSpacing is a temporary variable that should not be printed
|
|
// this->DataOrigin is a temporary variable that should not be printed
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkVolumeTextureMapper::ReportReferences(vtkGarbageCollector* collector)
|
|
{
|
|
this->Superclass::ReportReferences(collector);
|
|
// These filters share our input and are therefore involved in a
|
|
// reference loop.
|
|
vtkGarbageCollectorReport(collector, this->GradientEstimator,
|
|
"GradientEstimator");
|
|
}
|
|
|