Cloned library of VTK-5.0.0 with extra build files for internal package management.
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.
 
 
 
 
 
 

2536 lines
84 KiB

/*=========================================================================
Program: Visualization Toolkit
Module: $RCSfile: vtkVolumeRayCastCompositeFunction.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 "vtkVolumeRayCastCompositeFunction.h"
#include "vtkObjectFactory.h"
#include "vtkPiecewiseFunction.h"
#include "vtkVolume.h"
#include "vtkVolumeProperty.h"
#include "vtkVolumeRayCastMapper.h"
#include <math.h>
vtkCxxRevisionMacro(vtkVolumeRayCastCompositeFunction, "$Revision: 1.1 $");
vtkStandardNewMacro(vtkVolumeRayCastCompositeFunction);
#define VTK_REMAINING_OPACITY 0.02
// This is the templated function that actually casts a ray and computes
// The composite value. This version uses nearest neighbor interpolation
// and does not perform shading.
template <class T>
void vtkCastRay_NN_Unshaded( T *data_ptr, vtkVolumeRayCastDynamicInfo *dynamicInfo,
vtkVolumeRayCastStaticInfo *staticInfo )
{
int value=0;
unsigned char *grad_mag_ptr = NULL;
float accum_red_intensity;
float accum_green_intensity;
float accum_blue_intensity;
float remaining_opacity;
float opacity=0.0;
float gradient_opacity;
int loop;
int xinc, yinc, zinc;
int voxel[3];
float ray_position[3];
int prev_voxel[3];
float *SOTF;
float *CTF;
float *GTF;
float *GOTF;
int offset;
int steps_this_ray = 0;
int grad_op_is_constant;
float gradient_opacity_constant;
int num_steps;
float *ray_start, *ray_increment;
num_steps = dynamicInfo->NumberOfStepsToTake;
ray_start = dynamicInfo->TransformedStart;
ray_increment = dynamicInfo->TransformedIncrement;
SOTF = staticInfo->Volume->GetCorrectedScalarOpacityArray();
CTF = staticInfo->Volume->GetRGBArray();
GTF = staticInfo->Volume->GetGrayArray();
GOTF = staticInfo->Volume->GetGradientOpacityArray();
// Get the gradient opacity constant. If this number is greater than
// or equal to 0.0, then the gradient opacity transfer function is
// a constant at that value, otherwise it is not a constant function
gradient_opacity_constant = staticInfo->Volume->GetGradientOpacityConstant();
grad_op_is_constant = ( gradient_opacity_constant >= 0.0 );
// Move the increments into local variables
xinc = staticInfo->DataIncrement[0];
yinc = staticInfo->DataIncrement[1];
zinc = staticInfo->DataIncrement[2];
// Initialize the ray position and voxel location
ray_position[0] = ray_start[0];
ray_position[1] = ray_start[1];
ray_position[2] = ray_start[2];
voxel[0] = vtkRoundFuncMacro( ray_position[0] );
voxel[1] = vtkRoundFuncMacro( ray_position[1] );
voxel[2] = vtkRoundFuncMacro( ray_position[2] );
// So far we haven't accumulated anything
accum_red_intensity = 0.0;
accum_green_intensity = 0.0;
accum_blue_intensity = 0.0;
remaining_opacity = 1.0;
// Get a pointer to the gradient magnitudes for this volume
if ( !grad_op_is_constant )
{
grad_mag_ptr = staticInfo->GradientMagnitudes;
}
// Keep track of previous voxel to know when we step into a new one
// set it to something invalid to start with so that everything is
// computed first time through
prev_voxel[0] = voxel[0]-1;
prev_voxel[1] = voxel[1]-1;
prev_voxel[2] = voxel[2]-1;
// Two cases - we are working with a gray or RGB transfer
// function - break them up to make it more efficient
if ( staticInfo->ColorChannels == 1 )
{
// For each step along the ray
for ( loop = 0;
loop < num_steps && remaining_opacity > VTK_REMAINING_OPACITY;
loop++ )
{
// We've taken another step
steps_this_ray++;
// Access the value at this voxel location
if ( prev_voxel[0] != voxel[0] ||
prev_voxel[1] != voxel[1] ||
prev_voxel[2] != voxel[2] )
{
offset = voxel[2] * zinc + voxel[1] * yinc + voxel[0] * xinc;
value = *(data_ptr + offset);
opacity = SOTF[value];
if ( opacity )
{
if ( grad_op_is_constant )
{
gradient_opacity = gradient_opacity_constant;
}
else
{
gradient_opacity = GOTF[*(grad_mag_ptr + offset)];
}
opacity *= gradient_opacity;
}
prev_voxel[0] = voxel[0];
prev_voxel[1] = voxel[1];
prev_voxel[2] = voxel[2];
}
// Accumulate some light intensity and opacity
accum_red_intensity += ( opacity * remaining_opacity *
GTF[(value)] );
remaining_opacity *= (1.0 - opacity);
// Increment our position and compute our voxel location
ray_position[0] += ray_increment[0];
ray_position[1] += ray_increment[1];
ray_position[2] += ray_increment[2];
voxel[0] = vtkRoundFuncMacro( ray_position[0] );
voxel[1] = vtkRoundFuncMacro( ray_position[1] );
voxel[2] = vtkRoundFuncMacro( ray_position[2] );
}
accum_green_intensity = accum_red_intensity;
accum_blue_intensity = accum_red_intensity;
}
else if ( staticInfo->ColorChannels == 3 )
{
// For each step along the ray
for ( loop = 0;
loop < num_steps && remaining_opacity > VTK_REMAINING_OPACITY;
loop++ )
{
// We've taken another step
steps_this_ray++;
// Access the value at this voxel location
if ( prev_voxel[0] != voxel[0] ||
prev_voxel[1] != voxel[1] ||
prev_voxel[2] != voxel[2] )
{
offset = voxel[2] * zinc + voxel[1] * yinc + voxel[0] * xinc;
value = *(data_ptr + offset);
opacity = SOTF[value];
if ( opacity )
{
if ( grad_op_is_constant )
{
gradient_opacity = gradient_opacity_constant;
}
else
{
gradient_opacity = GOTF[*(grad_mag_ptr + offset)];
}
opacity *= gradient_opacity;
}
prev_voxel[0] = voxel[0];
prev_voxel[1] = voxel[1];
prev_voxel[2] = voxel[2];
}
// Accumulate some light intensity and opacity
accum_red_intensity += ( opacity * remaining_opacity *
CTF[(value)*3] );
accum_green_intensity += ( opacity * remaining_opacity *
CTF[(value)*3 + 1] );
accum_blue_intensity += ( opacity * remaining_opacity *
CTF[(value)*3 + 2] );
remaining_opacity *= (1.0 - opacity);
// Increment our position and compute our voxel location
ray_position[0] += ray_increment[0];
ray_position[1] += ray_increment[1];
ray_position[2] += ray_increment[2];
voxel[0] = vtkRoundFuncMacro( ray_position[0] );
voxel[1] = vtkRoundFuncMacro( ray_position[1] );
voxel[2] = vtkRoundFuncMacro( ray_position[2] );
}
}
// Cap the intensity value at 1.0
if ( accum_red_intensity > 1.0 )
{
accum_red_intensity = 1.0;
}
if ( accum_green_intensity > 1.0 )
{
accum_green_intensity = 1.0;
}
if ( accum_blue_intensity > 1.0 )
{
accum_blue_intensity = 1.0;
}
if( remaining_opacity < VTK_REMAINING_OPACITY )
{
remaining_opacity = 0.0;
}
// Set the return pixel value. The depth value is the distance to the
// center of the volume.
dynamicInfo->Color[0] = accum_red_intensity;
dynamicInfo->Color[1] = accum_green_intensity;
dynamicInfo->Color[2] = accum_blue_intensity;
dynamicInfo->Color[3] = 1.0 - remaining_opacity;
dynamicInfo->NumberOfStepsTaken = steps_this_ray;
}
// This is the templated function that actually casts a ray and computes
// the composite value. This version uses nearest neighbor and does
// perform shading.
template <class T>
void vtkCastRay_NN_Shaded( T *data_ptr, vtkVolumeRayCastDynamicInfo *dynamicInfo,
vtkVolumeRayCastStaticInfo *staticInfo )
{
int value;
unsigned char *grad_mag_ptr = NULL;
float accum_red_intensity;
float accum_green_intensity;
float accum_blue_intensity;
float remaining_opacity;
float opacity = 0.0;
float gradient_opacity;
int loop;
int xinc, yinc, zinc;
int voxel[3];
float ray_position[3];
int prev_voxel[3];
float *SOTF;
float *CTF;
float *GTF;
float *GOTF;
float *red_d_shade, *green_d_shade, *blue_d_shade;
float *red_s_shade, *green_s_shade, *blue_s_shade;
unsigned short *encoded_normals;
float red_shaded_value = 0.0;
float green_shaded_value = 0.0;
float blue_shaded_value = 0.0;
int offset;
int steps_this_ray = 0;
int grad_op_is_constant;
float gradient_opacity_constant;
int num_steps;
float *ray_start, *ray_increment;
num_steps = dynamicInfo->NumberOfStepsToTake;
ray_start = dynamicInfo->TransformedStart;
ray_increment = dynamicInfo->TransformedIncrement;
// Get diffuse shading table pointers
red_d_shade = staticInfo->RedDiffuseShadingTable;
green_d_shade = staticInfo->GreenDiffuseShadingTable;
blue_d_shade = staticInfo->BlueDiffuseShadingTable;
// Get specular shading table pointers
red_s_shade = staticInfo->RedSpecularShadingTable;
green_s_shade = staticInfo->GreenSpecularShadingTable;
blue_s_shade = staticInfo->BlueSpecularShadingTable;
// Get a pointer to the encoded normals for this volume
encoded_normals = staticInfo->EncodedNormals;
// Get the scalar opacity transfer function for this volume (which maps
// scalar input values to opacities)
SOTF = staticInfo->Volume->GetCorrectedScalarOpacityArray();
// Get the color transfer function for this volume (which maps
// scalar input values to RGB values)
CTF = staticInfo->Volume->GetRGBArray();
GTF = staticInfo->Volume->GetGrayArray();
// Get the gradient opacity transfer function for this volume (which maps
// gradient magnitudes to opacities)
GOTF = staticInfo->Volume->GetGradientOpacityArray();
// Get the gradient opacity constant. If this number is greater than
// or equal to 0.0, then the gradient opacity transfer function is
// a constant at that value, otherwise it is not a constant function
gradient_opacity_constant = staticInfo->Volume->GetGradientOpacityConstant();
grad_op_is_constant = ( gradient_opacity_constant >= 0.0 );
// Get a pointer to the gradient magnitudes for this volume
if ( !grad_op_is_constant )
{
grad_mag_ptr = staticInfo->GradientMagnitudes;
}
// Move the increments into local variables
xinc = staticInfo->DataIncrement[0];
yinc = staticInfo->DataIncrement[1];
zinc = staticInfo->DataIncrement[2];
// Initialize the ray position and voxel location
ray_position[0] = ray_start[0];
ray_position[1] = ray_start[1];
ray_position[2] = ray_start[2];
voxel[0] = vtkRoundFuncMacro( ray_position[0] );
voxel[1] = vtkRoundFuncMacro( ray_position[1] );
voxel[2] = vtkRoundFuncMacro( ray_position[2] );
// So far we haven't accumulated anything
accum_red_intensity = 0.0;
accum_green_intensity = 0.0;
accum_blue_intensity = 0.0;
remaining_opacity = 1.0;
// Keep track of previous voxel to know when we step into a new one
prev_voxel[0] = voxel[0]-1;
prev_voxel[1] = voxel[1]-1;
prev_voxel[2] = voxel[2]-1;
// Two cases - we are working with a gray or RGB transfer
// function - break them up to make it more efficient
if ( staticInfo->ColorChannels == 1 )
{
// For each step along the ray
for ( loop = 0;
loop < num_steps && remaining_opacity > VTK_REMAINING_OPACITY;
loop++ )
{
// We've taken another step
steps_this_ray++;
// Access the value at this voxel location and compute
// opacity and shaded value
if ( prev_voxel[0] != voxel[0] ||
prev_voxel[1] != voxel[1] ||
prev_voxel[2] != voxel[2] )
{
offset = voxel[2] * zinc + voxel[1] * yinc + voxel[0] * xinc;
value = *(data_ptr + offset);
// Get the opacity contributed by the scalar opacity transfer function
opacity = SOTF[value];
// Multiply by the opacity contributed by the gradient magnitude
// transfer function (don't both if opacity is already 0)
if ( opacity )
{
if ( grad_op_is_constant )
{
gradient_opacity = gradient_opacity_constant;
}
else
{
gradient_opacity = GOTF[*(grad_mag_ptr + offset)];
}
opacity *= gradient_opacity;
}
// Compute the red shaded value (only if there is some opacity)
// This is grey-scale so green and blue are the same as red
if ( opacity )
{
red_shaded_value = opacity * remaining_opacity *
( red_d_shade[*(encoded_normals + offset)] * GTF[value] +
red_s_shade[*(encoded_normals + offset)] );
}
else
{
red_shaded_value = 0.0;
}
prev_voxel[0] = voxel[0];
prev_voxel[1] = voxel[1];
prev_voxel[2] = voxel[2];
}
// Accumulate the shaded intensity and opacity of this sample
accum_red_intensity += red_shaded_value;
remaining_opacity *= (1.0 - opacity);
// Increment our position and compute our voxel location
ray_position[0] += ray_increment[0];
ray_position[1] += ray_increment[1];
ray_position[2] += ray_increment[2];
voxel[0] = vtkRoundFuncMacro( ray_position[0] );
voxel[1] = vtkRoundFuncMacro( ray_position[1] );
voxel[2] = vtkRoundFuncMacro( ray_position[2] );
}
accum_green_intensity = accum_red_intensity;
accum_blue_intensity = accum_red_intensity;
}
else if ( staticInfo->ColorChannels == 3 )
{
// For each step along the ray
for ( loop = 0;
loop < num_steps && remaining_opacity > VTK_REMAINING_OPACITY; loop++ )
{
// We've taken another step
steps_this_ray++;
// Access the value at this voxel location and compute
// opacity and shaded value
if ( prev_voxel[0] != voxel[0] ||
prev_voxel[1] != voxel[1] ||
prev_voxel[2] != voxel[2] )
{
offset = voxel[2] * zinc + voxel[1] * yinc + voxel[0] * xinc;
value = *(data_ptr + offset);
// Get the opacity contributed by the scalar opacity transfer function
opacity = SOTF[value];
// Multiply by the opacity contributed by the gradient magnitude
// transfer function (don't both if opacity is already 0)
if ( opacity )
{
if ( grad_op_is_constant )
{
gradient_opacity = gradient_opacity_constant;
}
else
{
gradient_opacity = GOTF[*(grad_mag_ptr + offset)];
}
opacity *= gradient_opacity;
}
// Compute the red, green, and blue shaded value (only if there
// is some opacity)
if ( opacity )
{
red_shaded_value = opacity * remaining_opacity *
( red_d_shade[*(encoded_normals + offset)] * CTF[value*3] +
red_s_shade[*(encoded_normals + offset)] );
green_shaded_value = opacity * remaining_opacity *
( green_d_shade[*(encoded_normals + offset)] * CTF[value*3 + 1] +
green_s_shade[*(encoded_normals + offset)] );
blue_shaded_value = opacity * remaining_opacity *
( blue_d_shade[*(encoded_normals + offset)] * CTF[value*3 + 2] +
blue_s_shade[*(encoded_normals + offset)] );
}
else
{
red_shaded_value = 0.0;
green_shaded_value = 0.0;
blue_shaded_value = 0.0;
}
prev_voxel[0] = voxel[0];
prev_voxel[1] = voxel[1];
prev_voxel[2] = voxel[2];
}
// Accumulate the shaded intensity and opacity of this sample
accum_red_intensity += red_shaded_value;
accum_green_intensity += green_shaded_value;
accum_blue_intensity += blue_shaded_value;
remaining_opacity *= (1.0 - opacity);
// Increment our position and compute our voxel location
ray_position[0] += ray_increment[0];
ray_position[1] += ray_increment[1];
ray_position[2] += ray_increment[2];
voxel[0] = vtkRoundFuncMacro( ray_position[0] );
voxel[1] = vtkRoundFuncMacro( ray_position[1] );
voxel[2] = vtkRoundFuncMacro( ray_position[2] );
}
}
// Cap the intensities at 1.0
if ( accum_red_intensity > 1.0 )
{
accum_red_intensity = 1.0;
}
if ( accum_green_intensity > 1.0 )
{
accum_green_intensity = 1.0;
}
if ( accum_blue_intensity > 1.0 )
{
accum_blue_intensity = 1.0;
}
if( remaining_opacity < VTK_REMAINING_OPACITY )
{
remaining_opacity = 0.0;
}
// Set the return pixel value. The depth value is the distance to the
// center of the volume.
dynamicInfo->Color[0] = accum_red_intensity;
dynamicInfo->Color[1] = accum_green_intensity;
dynamicInfo->Color[2] = accum_blue_intensity;
dynamicInfo->Color[3] = 1.0 - remaining_opacity;
dynamicInfo->NumberOfStepsTaken = steps_this_ray;
}
// This is the templated function that actually casts a ray and computes
// the composite value. This version uses trilinear interpolation and
// does not compute shading
template <class T>
void vtkCastRay_TrilinSample_Unshaded( T *data_ptr, vtkVolumeRayCastDynamicInfo *dynamicInfo,
vtkVolumeRayCastStaticInfo *staticInfo )
{
unsigned char *grad_mag_ptr = NULL;
unsigned char *gmptr;
float accum_red_intensity;
float accum_green_intensity;
float accum_blue_intensity;
float remaining_opacity;
float red_value, green_value, blue_value;
float opacity;
int loop;
int xinc, yinc, zinc;
int voxel[3];
float ray_position[3];
float A, B, C, D, E, F, G, H;
int Binc, Cinc, Dinc, Einc, Finc, Ginc, Hinc;
T *dptr;
float *SOTF;
float *CTF;
float *GTF;
float *GOTF;
float x, y, z, t1, t2, t3;
int offset;
int steps_this_ray = 0;
float gradient_value;
float scalar_value;
int grad_op_is_constant;
float gradient_opacity_constant;
int num_steps;
float *ray_start, *ray_increment;
num_steps = dynamicInfo->NumberOfStepsToTake;
ray_start = dynamicInfo->TransformedStart;
ray_increment = dynamicInfo->TransformedIncrement;
// Get the scalar opacity transfer function which maps scalar input values
// to opacities
SOTF = staticInfo->Volume->GetCorrectedScalarOpacityArray();
// Get the color transfer function which maps scalar input values
// to RGB colors
CTF = staticInfo->Volume->GetRGBArray();
GTF = staticInfo->Volume->GetGrayArray();
// Get the gradient opacity transfer function for this volume (which maps
// gradient magnitudes to opacities)
GOTF = staticInfo->Volume->GetGradientOpacityArray();
// Get the gradient opacity constant. If this number is greater than
// or equal to 0.0, then the gradient opacity transfer function is
// a constant at that value, otherwise it is not a constant function
gradient_opacity_constant = staticInfo->Volume->GetGradientOpacityConstant();
grad_op_is_constant = ( gradient_opacity_constant >= 0.0 );
// Get a pointer to the gradient magnitudes for this volume
if ( !grad_op_is_constant )
{
grad_mag_ptr = staticInfo->GradientMagnitudes;
}
// Move the increments into local variables
xinc = staticInfo->DataIncrement[0];
yinc = staticInfo->DataIncrement[1];
zinc = staticInfo->DataIncrement[2];
// Initialize the ray position and voxel location
ray_position[0] = ray_start[0];
ray_position[1] = ray_start[1];
ray_position[2] = ray_start[2];
voxel[0] = vtkFloorFuncMacro( ray_position[0] );
voxel[1] = vtkFloorFuncMacro( ray_position[1] );
voxel[2] = vtkFloorFuncMacro( ray_position[2] );
// So far we have not accumulated anything
accum_red_intensity = 0.0;
accum_green_intensity = 0.0;
accum_blue_intensity = 0.0;
remaining_opacity = 1.0;
// Compute the increments to get to the other 7 voxel vertices from A
Binc = xinc;
Cinc = yinc;
Dinc = xinc + yinc;
Einc = zinc;
Finc = zinc + xinc;
Ginc = zinc + yinc;
Hinc = zinc + xinc + yinc;
// Two cases - we are working with a gray or RGB transfer
// function - break them up to make it more efficient
if ( staticInfo->ColorChannels == 1 )
{
// For each step along the ray
for ( loop = 0;
loop < num_steps && remaining_opacity > VTK_REMAINING_OPACITY;
loop++ )
{
// We've taken another step
steps_this_ray++;
offset = voxel[2] * zinc + voxel[1] * yinc + voxel[0];
dptr = data_ptr + offset;
A = *(dptr);
B = *(dptr + Binc);
C = *(dptr + Cinc);
D = *(dptr + Dinc);
E = *(dptr + Einc);
F = *(dptr + Finc);
G = *(dptr + Ginc);
H = *(dptr + Hinc);
// Compute our offset in the voxel, and use that to trilinearly
// interpolate the value
x = ray_position[0] - (float) voxel[0];
y = ray_position[1] - (float) voxel[1];
z = ray_position[2] - (float) voxel[2];
t1 = 1.0 - x;
t2 = 1.0 - y;
t3 = 1.0 - z;
scalar_value =
A * t1 * t2 * t3 +
B * x * t2 * t3 +
C * t1 * y * t3 +
D * x * y * t3 +
E * t1 * t2 * z +
F * x * t2 * z +
G * t1 * y * z +
H * x * y * z;
if ( scalar_value < 0.0 )
{
scalar_value = 0.0;
}
else if ( scalar_value > staticInfo->Volume->GetArraySize() - 1 )
{
scalar_value = staticInfo->Volume->GetArraySize() - 1;
}
opacity = SOTF[(int)(scalar_value)];
if ( opacity )
{
if ( !grad_op_is_constant )
{
gmptr = grad_mag_ptr + offset;
A = *(gmptr);
B = *(gmptr + Binc);
C = *(gmptr + Cinc);
D = *(gmptr + Dinc);
E = *(gmptr + Einc);
F = *(gmptr + Finc);
G = *(gmptr + Ginc);
H = *(gmptr + Hinc);
gradient_value =
A * t1 * t2 * t3 +
B * x * t2 * t3 +
C * t1 * y * t3 +
D * x * y * t3 +
E * t1 * t2 * z +
F * x * t2 * z +
G * t1 * y * z +
H * x * y * z;
if ( gradient_value < 0.0 )
{
gradient_value = 0.0;
}
else if ( gradient_value > 255.0 )
{
gradient_value = 255.0;
}
opacity *= GOTF[(int)(gradient_value)];
}
else
{
opacity *= gradient_opacity_constant;
}
red_value = opacity * GTF[(int)(scalar_value)];
// Accumulate intensity and opacity for this sample location
accum_red_intensity += remaining_opacity * red_value;
remaining_opacity *= (1.0 - opacity);
}
// Increment our position and compute our voxel location
ray_position[0] += ray_increment[0];
ray_position[1] += ray_increment[1];
ray_position[2] += ray_increment[2];
voxel[0] = vtkFloorFuncMacro( ray_position[0] );
voxel[1] = vtkFloorFuncMacro( ray_position[1] );
voxel[2] = vtkFloorFuncMacro( ray_position[2] );
}
accum_green_intensity = accum_red_intensity;
accum_blue_intensity = accum_red_intensity;
}
else if ( staticInfo->ColorChannels == 3 )
{
// For each step along the ray
for ( loop = 0;
loop < num_steps && remaining_opacity > VTK_REMAINING_OPACITY;
loop++ )
{
// We've taken another step
steps_this_ray++;
offset = voxel[2] * zinc + voxel[1] * yinc + voxel[0];
dptr = data_ptr + offset;
A = *(dptr);
B = *(dptr + Binc);
C = *(dptr + Cinc);
D = *(dptr + Dinc);
E = *(dptr + Einc);
F = *(dptr + Finc);
G = *(dptr + Ginc);
H = *(dptr + Hinc);
// Compute our offset in the voxel, and use that to trilinearly
// interpolate the value
x = ray_position[0] - (float) voxel[0];
y = ray_position[1] - (float) voxel[1];
z = ray_position[2] - (float) voxel[2];
t1 = 1.0 - x;
t2 = 1.0 - y;
t3 = 1.0 - z;
scalar_value =
A * t1 * t2 * t3 +
B * x * t2 * t3 +
C * t1 * y * t3 +
D * x * y * t3 +
E * t1 * t2 * z +
F * x * t2 * z +
G * t1 * y * z +
H * x * y * z;
if ( scalar_value < 0.0 )
{
scalar_value = 0.0;
}
else if ( scalar_value > staticInfo->Volume->GetArraySize() - 1 )
{
scalar_value = staticInfo->Volume->GetArraySize() - 1;
}
opacity = SOTF[(int)(scalar_value)];
if ( opacity )
{
if ( !grad_op_is_constant )
{
gmptr = grad_mag_ptr + offset;
A = *(gmptr);
B = *(gmptr + Binc);
C = *(gmptr + Cinc);
D = *(gmptr + Dinc);
E = *(gmptr + Einc);
F = *(gmptr + Finc);
G = *(gmptr + Ginc);
H = *(gmptr + Hinc);
gradient_value =
A * t1 * t2 * t3 +
B * x * t2 * t3 +
C * t1 * y * t3 +
D * x * y * t3 +
E * t1 * t2 * z +
F * x * t2 * z +
G * t1 * y * z +
H * x * y * z;
if ( gradient_value < 0.0 )
{
gradient_value = 0.0;
}
else if ( gradient_value > 255.0 )
{
gradient_value = 255.0;
}
opacity *= GOTF[(int)(gradient_value)];
}
else
{
opacity *= gradient_opacity_constant;
}
red_value = opacity * CTF[(int)(scalar_value) * 3 ];
green_value = opacity * CTF[(int)(scalar_value) * 3 + 1];
blue_value = opacity * CTF[(int)(scalar_value) * 3 + 2];
// Accumulate intensity and opacity for this sample location
accum_red_intensity += remaining_opacity * red_value;
accum_green_intensity += remaining_opacity * green_value;
accum_blue_intensity += remaining_opacity * blue_value;
remaining_opacity *= (1.0 - opacity);
}
// Increment our position and compute our voxel location
ray_position[0] += ray_increment[0];
ray_position[1] += ray_increment[1];
ray_position[2] += ray_increment[2];
voxel[0] = vtkFloorFuncMacro( ray_position[0] );
voxel[1] = vtkFloorFuncMacro( ray_position[1] );
voxel[2] = vtkFloorFuncMacro( ray_position[2] );
}
}
// Cap the intensity value at 1.0
if ( accum_red_intensity > 1.0 )
{
accum_red_intensity = 1.0;
}
if ( accum_green_intensity > 1.0 )
{
accum_green_intensity = 1.0;
}
if ( accum_blue_intensity > 1.0 )
{
accum_blue_intensity = 1.0;
}
if( remaining_opacity < VTK_REMAINING_OPACITY )
{
remaining_opacity = 0.0;
}
// Set the return pixel value. The depth value is the distance to the
// center of the volume.
dynamicInfo->Color[0] = accum_red_intensity;
dynamicInfo->Color[1] = accum_green_intensity;
dynamicInfo->Color[2] = accum_blue_intensity;
dynamicInfo->Color[3] = 1.0 - remaining_opacity;
dynamicInfo->NumberOfStepsTaken = steps_this_ray;
}
// This is the templated function that actually casts a ray and computes
// the composite value. This version uses trilinear interpolation, and
// does perform shading.
template <class T>
void vtkCastRay_TrilinSample_Shaded( T *data_ptr, vtkVolumeRayCastDynamicInfo *dynamicInfo,
vtkVolumeRayCastStaticInfo *staticInfo )
{
unsigned char *grad_mag_ptr = NULL;
unsigned char *gmptr;
float accum_red_intensity;
float accum_green_intensity;
float accum_blue_intensity;
float remaining_opacity;
float opacity;
int loop;
int xinc, yinc, zinc;
int voxel[3];
float ray_position[3];
float A, B, C, D, E, F, G, H;
int A_n, B_n, C_n, D_n, E_n, F_n, G_n, H_n;
float final_rd, final_gd, final_bd;
float final_rs, final_gs, final_bs;
int Binc, Cinc, Dinc, Einc, Finc, Ginc, Hinc;
T *dptr;
float *SOTF;
float *CTF;
float *GTF;
float *GOTF;
float x, y, z, t1, t2, t3;
float tA, tB, tC, tD, tE, tF, tG, tH;
float *red_d_shade, *green_d_shade, *blue_d_shade;
float *red_s_shade, *green_s_shade, *blue_s_shade;
unsigned short *encoded_normals, *nptr;
float red_shaded_value, green_shaded_value, blue_shaded_value;
int offset;
int steps_this_ray = 0;
int gradient_value;
int scalar_value;
float r, g, b;
int grad_op_is_constant;
float gradient_opacity_constant;
int num_steps;
float *ray_start, *ray_increment;
num_steps = dynamicInfo->NumberOfStepsToTake;
ray_start = dynamicInfo->TransformedStart;
ray_increment = dynamicInfo->TransformedIncrement;
// Get diffuse shading table pointers
red_d_shade = staticInfo->RedDiffuseShadingTable;
green_d_shade = staticInfo->GreenDiffuseShadingTable;
blue_d_shade = staticInfo->BlueDiffuseShadingTable;
// Get diffuse shading table pointers
red_s_shade = staticInfo->RedSpecularShadingTable;
green_s_shade = staticInfo->GreenSpecularShadingTable;
blue_s_shade = staticInfo->BlueSpecularShadingTable;
// Get a pointer to the encoded normals for this volume
encoded_normals = staticInfo->EncodedNormals;
// Get the scalar opacity transfer function which maps scalar input values
// to opacities
SOTF = staticInfo->Volume->GetCorrectedScalarOpacityArray();
// Get the color transfer function which maps scalar input values
// to RGB values
CTF = staticInfo->Volume->GetRGBArray();
GTF = staticInfo->Volume->GetGrayArray();
// Get the gradient opacity transfer function for this volume (which maps
// gradient magnitudes to opacities)
GOTF = staticInfo->Volume->GetGradientOpacityArray();
// Get the gradient opacity constant. If this number is greater than
// or equal to 0.0, then the gradient opacity transfer function is
// a constant at that value, otherwise it is not a constant function
gradient_opacity_constant = staticInfo->Volume->GetGradientOpacityConstant();
grad_op_is_constant = ( gradient_opacity_constant >= 0.0 );
// Get a pointer to the gradient magnitudes for this volume
if ( !grad_op_is_constant )
{
grad_mag_ptr = staticInfo->GradientMagnitudes;
}
// Move the increments into local variables
xinc = staticInfo->DataIncrement[0];
yinc = staticInfo->DataIncrement[1];
zinc = staticInfo->DataIncrement[2];
// Initialize the ray position and voxel location
ray_position[0] = ray_start[0];
ray_position[1] = ray_start[1];
ray_position[2] = ray_start[2];
voxel[0] = vtkFloorFuncMacro( ray_position[0] );
voxel[1] = vtkFloorFuncMacro( ray_position[1] );
voxel[2] = vtkFloorFuncMacro( ray_position[2] );
// So far we haven't accumulated anything
accum_red_intensity = 0.0;
accum_green_intensity = 0.0;
accum_blue_intensity = 0.0;
remaining_opacity = 1.0;
// Compute the increments to get to the other 7 voxel vertices from A
Binc = xinc;
Cinc = yinc;
Dinc = xinc + yinc;
Einc = zinc;
Finc = zinc + xinc;
Ginc = zinc + yinc;
Hinc = zinc + xinc + yinc;
// Two cases - we are working with a gray or RGB transfer
// function - break them up to make it more efficient
if ( staticInfo->ColorChannels == 1 )
{
// For each step along the ray
for ( loop = 0;
loop < num_steps && remaining_opacity > VTK_REMAINING_OPACITY;
loop++ )
{
// We've taken another step
steps_this_ray++;
offset = voxel[2] * zinc + voxel[1] * yinc + voxel[0];
dptr = data_ptr + offset;
nptr = encoded_normals + offset;
A = *(dptr);
B = *(dptr + Binc);
C = *(dptr + Cinc);
D = *(dptr + Dinc);
E = *(dptr + Einc);
F = *(dptr + Finc);
G = *(dptr + Ginc);
H = *(dptr + Hinc);
// Compute our offset in the voxel, and use that to trilinearly
// interpolate a value
x = ray_position[0] - (float) voxel[0];
y = ray_position[1] - (float) voxel[1];
z = ray_position[2] - (float) voxel[2];
t1 = 1.0 - x;
t2 = 1.0 - y;
t3 = 1.0 - z;
tA = t1 * t2 * t3;
tB = x * t2 * t3;
tC = t1 * y * t3;
tD = x * y * t3;
tE = t1 * t2 * z;
tF = x * t2 * z;
tG = t1 * y * z;
tH = x * y * z;
scalar_value = (int) (
A * tA + B * tB + C * tC + D * tD +
E * tE + F * tF + G * tG + H * tH );
if ( scalar_value < 0 )
{
scalar_value = 0;
}
else if ( scalar_value > staticInfo->Volume->GetArraySize() - 1 )
{
scalar_value = (int)(staticInfo->Volume->GetArraySize() - 1);
}
opacity = SOTF[scalar_value];
// If we have some opacity based on the scalar value transfer function,
// then multiply by the opacity from the gradient magnitude transfer
// function
if ( opacity )
{
if ( !grad_op_is_constant )
{
gmptr = grad_mag_ptr + offset;
A = *(gmptr);
B = *(gmptr + Binc);
C = *(gmptr + Cinc);
D = *(gmptr + Dinc);
E = *(gmptr + Einc);
F = *(gmptr + Finc);
G = *(gmptr + Ginc);
H = *(gmptr + Hinc);
gradient_value = (int) (
A * tA + B * tB + C * tC + D * tD +
E * tE + F * tF + G * tG + H * tH );
if ( gradient_value < 0 )
{
gradient_value = 0;
}
else if ( gradient_value > 255 )
{
gradient_value = 255;
}
opacity *= GOTF[gradient_value];
}
else
{
opacity *= gradient_opacity_constant;
}
}
// If we have a combined opacity value, then compute the shading
if ( opacity )
{
A_n = *(nptr);
B_n = *(nptr + Binc);
C_n = *(nptr + Cinc);
D_n = *(nptr + Dinc);
E_n = *(nptr + Einc);
F_n = *(nptr + Finc);
G_n = *(nptr + Ginc);
H_n = *(nptr + Hinc);
final_rd =
red_d_shade[ A_n ] * tA + red_d_shade[ B_n ] * tB +
red_d_shade[ C_n ] * tC + red_d_shade[ D_n ] * tD +
red_d_shade[ E_n ] * tE + red_d_shade[ F_n ] * tF +
red_d_shade[ G_n ] * tG + red_d_shade[ H_n ] * tH;
final_rs =
red_s_shade[ A_n ] * tA + red_s_shade[ B_n ] * tB +
red_s_shade[ C_n ] * tC + red_s_shade[ D_n ] * tD +
red_s_shade[ E_n ] * tE + red_s_shade[ F_n ] * tF +
red_s_shade[ G_n ] * tG + red_s_shade[ H_n ] * tH;
r = GTF[(scalar_value)];
// For this sample we have do not yet have any opacity or
// shaded intensity yet
red_shaded_value = opacity * ( final_rd * r + final_rs );
// Accumulate intensity and opacity for this sample location
accum_red_intensity += red_shaded_value * remaining_opacity;
remaining_opacity *= (1.0 - opacity);
}
// Increment our position and compute our voxel location
ray_position[0] += ray_increment[0];
ray_position[1] += ray_increment[1];
ray_position[2] += ray_increment[2];
voxel[0] = vtkFloorFuncMacro( ray_position[0] );
voxel[1] = vtkFloorFuncMacro( ray_position[1] );
voxel[2] = vtkFloorFuncMacro( ray_position[2] );
}
accum_green_intensity = accum_red_intensity;
accum_blue_intensity = accum_red_intensity;
}
else if ( staticInfo->ColorChannels == 3 )
{
// For each step along the ray
for ( loop = 0;
loop < num_steps && remaining_opacity > VTK_REMAINING_OPACITY;
loop++ )
{
// We've taken another step
steps_this_ray++;
offset = voxel[2] * zinc + voxel[1] * yinc + voxel[0];
dptr = data_ptr + offset;
nptr = encoded_normals + offset;
A = *(dptr);
B = *(dptr + Binc);
C = *(dptr + Cinc);
D = *(dptr + Dinc);
E = *(dptr + Einc);
F = *(dptr + Finc);
G = *(dptr + Ginc);
H = *(dptr + Hinc);
// Compute our offset in the voxel, and use that to trilinearly
// interpolate a value
x = ray_position[0] - (float) voxel[0];
y = ray_position[1] - (float) voxel[1];
z = ray_position[2] - (float) voxel[2];
t1 = 1.0 - x;
t2 = 1.0 - y;
t3 = 1.0 - z;
tA = t1 * t2 * t3;
tB = x * t2 * t3;
tC = t1 * y * t3;
tD = x * y * t3;
tE = t1 * t2 * z;
tF = x * t2 * z;
tG = t1 * y * z;
tH = x * y * z;
scalar_value = (int) (
A * tA + B * tB + C * tC + D * tD +
E * tE + F * tF + G * tG + H * tH );
if ( scalar_value < 0 )
{
scalar_value = 0;
}
else if ( scalar_value > staticInfo->Volume->GetArraySize() - 1 )
{
scalar_value = (int)(staticInfo->Volume->GetArraySize() - 1);
}
opacity = SOTF[scalar_value];
if ( opacity )
{
if ( !grad_op_is_constant )
{
gmptr = grad_mag_ptr + offset;
A = *(gmptr);
B = *(gmptr + Binc);
C = *(gmptr + Cinc);
D = *(gmptr + Dinc);
E = *(gmptr + Einc);
F = *(gmptr + Finc);
G = *(gmptr + Ginc);
H = *(gmptr + Hinc);
gradient_value = (int) (
A * tA + B * tB + C * tC + D * tD +
E * tE + F * tF + G * tG + H * tH );
if ( gradient_value < 0 )
{
gradient_value = 0;
}
else if ( gradient_value > 255 )
{
gradient_value = 255;
}
opacity *= GOTF[gradient_value];
}
else
{
opacity *= gradient_opacity_constant;
}
}
// If we have a combined opacity value, then compute the shading
if ( opacity )
{
A_n = *(nptr);
B_n = *(nptr + Binc);
C_n = *(nptr + Cinc);
D_n = *(nptr + Dinc);
E_n = *(nptr + Einc);
F_n = *(nptr + Finc);
G_n = *(nptr + Ginc);
H_n = *(nptr + Hinc);
final_rd =
red_d_shade[ A_n ] * tA + red_d_shade[ B_n ] * tB +
red_d_shade[ C_n ] * tC + red_d_shade[ D_n ] * tD +
red_d_shade[ E_n ] * tE + red_d_shade[ F_n ] * tF +
red_d_shade[ G_n ] * tG + red_d_shade[ H_n ] * tH;
final_gd =
green_d_shade[ A_n ] * tA + green_d_shade[ B_n ] * tB +
green_d_shade[ C_n ] * tC + green_d_shade[ D_n ] * tD +
green_d_shade[ E_n ] * tE + green_d_shade[ F_n ] * tF +
green_d_shade[ G_n ] * tG + green_d_shade[ H_n ] * tH;
final_bd =
blue_d_shade[ A_n ] * tA + blue_d_shade[ B_n ] * tB +
blue_d_shade[ C_n ] * tC + blue_d_shade[ D_n ] * tD +
blue_d_shade[ E_n ] * tE + blue_d_shade[ F_n ] * tF +
blue_d_shade[ G_n ] * tG + blue_d_shade[ H_n ] * tH;
final_rs =
red_s_shade[ A_n ] * tA + red_s_shade[ B_n ] * tB +
red_s_shade[ C_n ] * tC + red_s_shade[ D_n ] * tD +
red_s_shade[ E_n ] * tE + red_s_shade[ F_n ] * tF +
red_s_shade[ G_n ] * tG + red_s_shade[ H_n ] * tH;
final_gs =
green_s_shade[ A_n ] * tA + green_s_shade[ B_n ] * tB +
green_s_shade[ C_n ] * tC + green_s_shade[ D_n ] * tD +
green_s_shade[ E_n ] * tE + green_s_shade[ F_n ] * tF +
green_s_shade[ G_n ] * tG + green_s_shade[ H_n ] * tH;
final_bs =
blue_s_shade[ A_n ] * tA + blue_s_shade[ B_n ] * tB +
blue_s_shade[ C_n ] * tC + blue_s_shade[ D_n ] * tD +
blue_s_shade[ E_n ] * tE + blue_s_shade[ F_n ] * tF +
blue_s_shade[ G_n ] * tG + blue_s_shade[ H_n ] * tH;
r = CTF[(scalar_value) * 3 ];
g = CTF[(scalar_value) * 3 + 1];
b = CTF[(scalar_value) * 3 + 2];
// For this sample we have do not yet have any opacity or
// shaded intensity yet
red_shaded_value = opacity * ( final_rd * r + final_rs );
green_shaded_value = opacity * ( final_gd * g + final_gs );
blue_shaded_value = opacity * ( final_bd * b + final_bs );
// Accumulate intensity and opacity for this sample location
accum_red_intensity += red_shaded_value * remaining_opacity;
accum_green_intensity += green_shaded_value * remaining_opacity;
accum_blue_intensity += blue_shaded_value * remaining_opacity;
remaining_opacity *= (1.0 - opacity);
}
// Increment our position and compute our voxel location
ray_position[0] += ray_increment[0];
ray_position[1] += ray_increment[1];
ray_position[2] += ray_increment[2];
voxel[0] = vtkFloorFuncMacro( ray_position[0] );
voxel[1] = vtkFloorFuncMacro( ray_position[1] );
voxel[2] = vtkFloorFuncMacro( ray_position[2] );
}
}
// Cap the accumulated intensity at 1.0
if ( accum_red_intensity > 1.0 )
{
accum_red_intensity = 1.0;
}
if ( accum_green_intensity > 1.0 )
{
accum_green_intensity = 1.0;
}
if ( accum_blue_intensity > 1.0 )
{
accum_blue_intensity = 1.0;
}
if( remaining_opacity < VTK_REMAINING_OPACITY )
{
remaining_opacity = 0.0;
}
// Set the return pixel value. The depth value is the distance to the
// center of the volume.
dynamicInfo->Color[0] = accum_red_intensity;
dynamicInfo->Color[1] = accum_green_intensity;
dynamicInfo->Color[2] = accum_blue_intensity;
dynamicInfo->Color[3] = 1.0 - remaining_opacity;
dynamicInfo->NumberOfStepsTaken = steps_this_ray;
}
// Description:
// This is the templated function that actually casts a ray and computes
// the composite value. This version uses trilinear interpolation and
// does not compute shading
template <class T>
void vtkCastRay_TrilinVertices_Unshaded( T *data_ptr, vtkVolumeRayCastDynamicInfo *dynamicInfo,
vtkVolumeRayCastStaticInfo *staticInfo )
{
unsigned char *grad_mag_ptr = NULL;
unsigned char *goptr;
float accum_red_intensity;
float accum_green_intensity;
float accum_blue_intensity;
float remaining_opacity;
float red_value, green_value, blue_value;
float opacity;
int loop;
int xinc, yinc, zinc;
int voxel[3];
float ray_position[3];
int prev_voxel[3];
float A, B, C, D, E, F, G, H;
float Ago, Bgo, Cgo, Dgo, Ego, Fgo, Ggo, Hgo;
int Binc, Cinc, Dinc, Einc, Finc, Ginc, Hinc;
T *dptr;
float *SOTF;
float *CTF;
float *GTF;
float *GOTF;
float x, y, z, t1, t2, t3;
float weight;
int offset;
int steps_this_ray = 0;
int num_steps;
float *ray_start, *ray_increment;
int grad_op_is_constant;
float gradient_opacity_constant;
num_steps = dynamicInfo->NumberOfStepsToTake;
ray_start = dynamicInfo->TransformedStart;
ray_increment = dynamicInfo->TransformedIncrement;
// Get the scalar opacity transfer function which maps scalar input values
// to opacities
SOTF = staticInfo->Volume->GetCorrectedScalarOpacityArray();
// Get the color transfer function which maps scalar input values
// to RGB colors
CTF = staticInfo->Volume->GetRGBArray();
GTF = staticInfo->Volume->GetGrayArray();
// Get the gradient opacity transfer function for this volume (which maps
// gradient magnitudes to opacities)
GOTF = staticInfo->Volume->GetGradientOpacityArray();
// Get the gradient opacity constant. If this number is greater than
// or equal to 0.0, then the gradient opacity transfer function is
// a constant at that value, otherwise it is not a constant function
gradient_opacity_constant = staticInfo->Volume->GetGradientOpacityConstant();
grad_op_is_constant = ( gradient_opacity_constant >= 0.0 );
// Get a pointer to the gradient magnitudes for this volume
if ( !grad_op_is_constant )
{
grad_mag_ptr = staticInfo->GradientMagnitudes;
}
// Move the increments into local variables
xinc = staticInfo->DataIncrement[0];
yinc = staticInfo->DataIncrement[1];
zinc = staticInfo->DataIncrement[2];
// Initialize the ray position and voxel location
ray_position[0] = ray_start[0];
ray_position[1] = ray_start[1];
ray_position[2] = ray_start[2];
voxel[0] = vtkFloorFuncMacro( ray_position[0] );
voxel[1] = vtkFloorFuncMacro( ray_position[1] );
voxel[2] = vtkFloorFuncMacro( ray_position[2] );
// So far we have not accumulated anything
accum_red_intensity = 0.0;
accum_green_intensity = 0.0;
accum_blue_intensity = 0.0;
remaining_opacity = 1.0;
// Compute the increments to get to the other 7 voxel vertices from A
Binc = xinc;
Cinc = yinc;
Dinc = xinc + yinc;
Einc = zinc;
Finc = zinc + xinc;
Ginc = zinc + yinc;
Hinc = zinc + xinc + yinc;
// Compute the values for the first pass through the loop
offset = voxel[2] * zinc + voxel[1] * yinc + voxel[0];
dptr = data_ptr + offset;
A = SOTF[(*(dptr))];
B = SOTF[(*(dptr + Binc))];
C = SOTF[(*(dptr + Cinc))];
D = SOTF[(*(dptr + Dinc))];
E = SOTF[(*(dptr + Einc))];
F = SOTF[(*(dptr + Finc))];
G = SOTF[(*(dptr + Ginc))];
H = SOTF[(*(dptr + Hinc))];
if ( !grad_op_is_constant )
{
goptr = grad_mag_ptr + offset;
Ago = GOTF[(*(goptr))];
Bgo = GOTF[(*(goptr + Binc))];
Cgo = GOTF[(*(goptr + Cinc))];
Dgo = GOTF[(*(goptr + Dinc))];
Ego = GOTF[(*(goptr + Einc))];
Fgo = GOTF[(*(goptr + Finc))];
Ggo = GOTF[(*(goptr + Ginc))];
Hgo = GOTF[(*(goptr + Hinc))];
}
else
{
Ago = Bgo = Cgo = Dgo = Ego = Fgo = Ggo = Hgo = 1.0;
}
// Keep track of previous voxel to know when we step into a new one
prev_voxel[0] = voxel[0];
prev_voxel[1] = voxel[1];
prev_voxel[2] = voxel[2];
// Two cases - we are working with a gray or RGB transfer
// function - break them up to make it more efficient
if ( staticInfo->ColorChannels == 1 )
{
// For each step along the ray
for ( loop = 0;
loop < num_steps && remaining_opacity > VTK_REMAINING_OPACITY;
loop++ )
{
// We've taken another step
steps_this_ray++;
// Have we moved into a new voxel? If so we need to recompute A-H
if ( prev_voxel[0] != voxel[0] ||
prev_voxel[1] != voxel[1] ||
prev_voxel[2] != voxel[2] )
{
offset = voxel[2] * zinc + voxel[1] * yinc + voxel[0];
dptr = data_ptr + offset;
A = SOTF[(*(dptr))];
B = SOTF[(*(dptr + Binc))];
C = SOTF[(*(dptr + Cinc))];
D = SOTF[(*(dptr + Dinc))];
E = SOTF[(*(dptr + Einc))];
F = SOTF[(*(dptr + Finc))];
G = SOTF[(*(dptr + Ginc))];
H = SOTF[(*(dptr + Hinc))];
if ( !grad_op_is_constant )
{
goptr = grad_mag_ptr + offset;
Ago = GOTF[(*(goptr))];
Bgo = GOTF[(*(goptr + Binc))];
Cgo = GOTF[(*(goptr + Cinc))];
Dgo = GOTF[(*(goptr + Dinc))];
Ego = GOTF[(*(goptr + Einc))];
Fgo = GOTF[(*(goptr + Finc))];
Ggo = GOTF[(*(goptr + Ginc))];
Hgo = GOTF[(*(goptr + Hinc))];
}
else
{
Ago = Bgo = Cgo = Dgo = Ego = Fgo = Ggo = Hgo = 1.0;
}
prev_voxel[0] = voxel[0];
prev_voxel[1] = voxel[1];
prev_voxel[2] = voxel[2];
}
// Compute our offset in the voxel, and use that to trilinearly
// interpolate the value
x = ray_position[0] - (float) voxel[0];
y = ray_position[1] - (float) voxel[1];
z = ray_position[2] - (float) voxel[2];
t1 = 1.0 - x;
t2 = 1.0 - y;
t3 = 1.0 - z;
// For this sample we have do not yet have any opacity
opacity = 0.0;
red_value = 0.0;
// Now add the opacity in vertex by vertex. If any of the A-H
// have a non-transparent opacity value, then add its contribution
// to the opacity
if ( A && Ago )
{
weight = t1*t2*t3 * A * Ago;
opacity += weight;
red_value += weight * GTF[((*dptr))];
}
if ( B && Bgo )
{
weight = x*t2*t3 * B * Bgo;
opacity += weight;
red_value += weight * GTF[((*(dptr + Binc)))];
}
if ( C && Cgo )
{
weight = t1*y*t3 * C * Cgo;
opacity += weight;
red_value += weight * GTF[((*(dptr + Cinc)))];
}
if ( D && Dgo )
{
weight = x*y*t3 * D * Dgo;
opacity += weight;
red_value += weight * GTF[((*(dptr + Dinc)))];
}
if ( E && Ego )
{
weight = t1*t2*z * E * Ego;
opacity += weight;
red_value += weight * GTF[((*(dptr + Einc)))];
}
if ( F && Fgo )
{
weight = x*t2*z * F * Fgo;
opacity += weight;
red_value += weight * GTF[((*(dptr + Finc)))];
}
if ( G && Ggo )
{
weight = t1*y*z * G * Ggo;
opacity += weight;
red_value += weight * GTF[((*(dptr + Ginc)))];
}
if ( H && Hgo )
{
weight = x*z*y * H * Hgo;
opacity += weight;
red_value += weight * GTF[((*(dptr + Hinc)))];
}
// Accumulate intensity and opacity for this sample location
accum_red_intensity += remaining_opacity * red_value;
remaining_opacity *= (1.0 - opacity);
// Increment our position and compute our voxel location
ray_position[0] += ray_increment[0];
ray_position[1] += ray_increment[1];
ray_position[2] += ray_increment[2];
voxel[0] = vtkFloorFuncMacro( ray_position[0] );
voxel[1] = vtkFloorFuncMacro( ray_position[1] );
voxel[2] = vtkFloorFuncMacro( ray_position[2] );
}
accum_green_intensity = accum_red_intensity;
accum_blue_intensity = accum_red_intensity;
}
else if ( staticInfo->ColorChannels == 3 )
{
// For each step along the ray
for ( loop = 0;
loop < num_steps && remaining_opacity > VTK_REMAINING_OPACITY;
loop++ )
{
// We've taken another step
steps_this_ray++;
// Have we moved into a new voxel? If so we need to recompute A-H
if ( prev_voxel[0] != voxel[0] ||
prev_voxel[1] != voxel[1] ||
prev_voxel[2] != voxel[2] )
{
offset = voxel[2] * zinc + voxel[1] * yinc + voxel[0];
dptr = data_ptr + offset;
A = SOTF[(*(dptr))];
B = SOTF[(*(dptr + Binc))];
C = SOTF[(*(dptr + Cinc))];
D = SOTF[(*(dptr + Dinc))];
E = SOTF[(*(dptr + Einc))];
F = SOTF[(*(dptr + Finc))];
G = SOTF[(*(dptr + Ginc))];
H = SOTF[(*(dptr + Hinc))];
if ( !grad_op_is_constant )
{
goptr = grad_mag_ptr + offset;
Ago = GOTF[(*(goptr))];
Bgo = GOTF[(*(goptr + Binc))];
Cgo = GOTF[(*(goptr + Cinc))];
Dgo = GOTF[(*(goptr + Dinc))];
Ego = GOTF[(*(goptr + Einc))];
Fgo = GOTF[(*(goptr + Finc))];
Ggo = GOTF[(*(goptr + Ginc))];
Hgo = GOTF[(*(goptr + Hinc))];
}
else
{
Ago = Bgo = Cgo = Dgo = Ego = Fgo = Ggo = Hgo = 1.0;
}
prev_voxel[0] = voxel[0];
prev_voxel[1] = voxel[1];
prev_voxel[2] = voxel[2];
}
// Compute our offset in the voxel, and use that to trilinearly
// interpolate the value
x = ray_position[0] - (float) voxel[0];
y = ray_position[1] - (float) voxel[1];
z = ray_position[2] - (float) voxel[2];
t1 = 1.0 - x;
t2 = 1.0 - y;
t3 = 1.0 - z;
// For this sample we have do not yet have any opacity
opacity = 0.0;
red_value = 0.0;
green_value = 0.0;
blue_value = 0.0;
// Now add the opacity in vertex by vertex. If any of the A-H
// have a non-transparent opacity value, then add its contribution
// to the opacity
if ( A && Ago )
{
weight = t1*t2*t3 * A * Ago;
opacity += weight;
red_value += weight * CTF[((*dptr)) * 3 ];
green_value += weight * CTF[((*dptr)) * 3 + 1];
blue_value += weight * CTF[((*dptr)) * 3 + 2];
}
if ( B && Bgo )
{
weight = x*t2*t3 * B * Bgo;
opacity += weight;
red_value += weight * CTF[((*(dptr + Binc))) * 3 ];
green_value += weight * CTF[((*(dptr + Binc))) * 3 + 1];
blue_value += weight * CTF[((*(dptr + Binc))) * 3 + 2];
}
if ( C && Cgo )
{
weight = t1*y*t3 * C * Cgo;
opacity += weight;
red_value += weight * CTF[((*(dptr + Cinc))) * 3 ];
green_value += weight * CTF[((*(dptr + Cinc))) * 3 + 1];
blue_value += weight * CTF[((*(dptr + Cinc))) * 3 + 2];
}
if ( D && Dgo )
{
weight = x*y*t3 * D * Dgo;
opacity += weight;
red_value += weight * CTF[((*(dptr + Dinc))) * 3 ];
green_value += weight * CTF[((*(dptr + Dinc))) * 3 + 1];
blue_value += weight * CTF[((*(dptr + Dinc))) * 3 + 2];
}
if ( E && Ego )
{
weight = t1*t2*z * E * Ego;
opacity += weight;
red_value += weight * CTF[((*(dptr + Einc))) * 3 ];
green_value += weight * CTF[((*(dptr + Einc))) * 3 + 1];
blue_value += weight * CTF[((*(dptr + Einc))) * 3 + 2];
}
if ( F && Fgo )
{
weight = x*t2*z * F * Fgo;
opacity += weight;
red_value += weight * CTF[((*(dptr + Finc))) * 3 ];
green_value += weight * CTF[((*(dptr + Finc))) * 3 + 1];
blue_value += weight * CTF[((*(dptr + Finc))) * 3 + 2];
}
if ( G && Ggo )
{
weight = t1*y*z * G * Ggo;
opacity += weight;
red_value += weight * CTF[((*(dptr + Ginc))) * 3 ];
green_value += weight * CTF[((*(dptr + Ginc))) * 3 + 1];
blue_value += weight * CTF[((*(dptr + Ginc))) * 3 + 2];
}
if ( H && Hgo )
{
weight = x*z*y * H * Hgo;
opacity += weight;
red_value += weight * CTF[((*(dptr + Hinc))) * 3 ];
green_value += weight * CTF[((*(dptr + Hinc))) * 3 + 1];
blue_value += weight * CTF[((*(dptr + Hinc))) * 3 + 2];
}
// Accumulate intensity and opacity for this sample location
accum_red_intensity += remaining_opacity * red_value;
accum_green_intensity += remaining_opacity * green_value;
accum_blue_intensity += remaining_opacity * blue_value;
remaining_opacity *= (1.0 - opacity);
// Increment our position and compute our voxel location
ray_position[0] += ray_increment[0];
ray_position[1] += ray_increment[1];
ray_position[2] += ray_increment[2];
voxel[0] = vtkFloorFuncMacro( ray_position[0] );
voxel[1] = vtkFloorFuncMacro( ray_position[1] );
voxel[2] = vtkFloorFuncMacro( ray_position[2] );
}
}
// Cap the accumulated intensity at 1.0
if ( accum_red_intensity > 1.0 )
{
accum_red_intensity = 1.0;
}
if ( accum_green_intensity > 1.0 )
{
accum_green_intensity = 1.0;
}
if ( accum_blue_intensity > 1.0 )
{
accum_blue_intensity = 1.0;
}
if( remaining_opacity < VTK_REMAINING_OPACITY )
{
remaining_opacity = 0.0;
}
// Set the return pixel value. The depth value is the distance to the
// center of the volume.
dynamicInfo->Color[0] = accum_red_intensity;
dynamicInfo->Color[1] = accum_green_intensity;
dynamicInfo->Color[2] = accum_blue_intensity;
dynamicInfo->Color[3] = 1.0 - remaining_opacity;
dynamicInfo->NumberOfStepsTaken = steps_this_ray;
}
// Description:
// This is the templated function that actually casts a ray and computes
// the composite value. This version uses trilinear interpolation, and
// does perform shading.
template <class T>
void vtkCastRay_TrilinVertices_Shaded( T *data_ptr, vtkVolumeRayCastDynamicInfo *dynamicInfo,
vtkVolumeRayCastStaticInfo *staticInfo )
{
unsigned char *grad_mag_ptr = NULL;
unsigned char *goptr;
float accum_red_intensity;
float accum_green_intensity;
float accum_blue_intensity;
float remaining_opacity;
float opacity;
int loop;
int xinc, yinc, zinc;
int voxel[3];
float ray_position[3];
int prev_voxel[3];
float A, B, C, D, E, F, G, H;
float Ago, Bgo, Cgo, Dgo, Ego, Fgo, Ggo, Hgo;
int Binc, Cinc, Dinc, Einc, Finc, Ginc, Hinc;
T *dptr;
float *SOTF;
float *CTF;
float *GTF;
float *GOTF;
float x, y, z, t1, t2, t3;
float weight;
float *red_d_shade, *green_d_shade, *blue_d_shade;
float *red_s_shade, *green_s_shade, *blue_s_shade;
unsigned short *encoded_normals, *nptr;
float red_shaded_value, green_shaded_value, blue_shaded_value;
int offset;
int steps_this_ray = 0;
int grad_op_is_constant;
float gradient_opacity_constant;
int num_steps;
float *ray_start, *ray_increment;
num_steps = dynamicInfo->NumberOfStepsToTake;
ray_start = dynamicInfo->TransformedStart;
ray_increment = dynamicInfo->TransformedIncrement;
// Get diffuse shading table pointers
red_d_shade = staticInfo->RedDiffuseShadingTable;
green_d_shade = staticInfo->GreenDiffuseShadingTable;
blue_d_shade = staticInfo->BlueDiffuseShadingTable;
// Get diffuse shading table pointers
red_s_shade = staticInfo->RedSpecularShadingTable;
green_s_shade = staticInfo->GreenSpecularShadingTable;
blue_s_shade = staticInfo->BlueSpecularShadingTable;
// Get a pointer to the encoded normals for this volume
encoded_normals = staticInfo->EncodedNormals;
// Get the scalar opacity transfer function which maps scalar input values
// to opacities
SOTF = staticInfo->Volume->GetCorrectedScalarOpacityArray();
// Get the color transfer function which maps scalar input values
// to RGB values
CTF = staticInfo->Volume->GetRGBArray();
GTF = staticInfo->Volume->GetGrayArray();
// Get the gradient opacity transfer function for this volume (which maps
// gradient magnitudes to opacities)
GOTF = staticInfo->Volume->GetGradientOpacityArray();
// Get the gradient opacity constant. If this number is greater than
// or equal to 0.0, then the gradient opacity transfer function is
// a constant at that value, otherwise it is not a constant function
gradient_opacity_constant = staticInfo->Volume->GetGradientOpacityConstant();
grad_op_is_constant = ( gradient_opacity_constant >= 0.0 );
// Get a pointer to the gradient magnitudes for this volume
if ( !grad_op_is_constant )
{
grad_mag_ptr = staticInfo->GradientMagnitudes;
}
// Move the increments into local variables
xinc = staticInfo->DataIncrement[0];
yinc = staticInfo->DataIncrement[1];
zinc = staticInfo->DataIncrement[2];
// Initialize the ray position and voxel location
ray_position[0] = ray_start[0];
ray_position[1] = ray_start[1];
ray_position[2] = ray_start[2];
voxel[0] = vtkFloorFuncMacro( ray_position[0] );
voxel[1] = vtkFloorFuncMacro( ray_position[1] );
voxel[2] = vtkFloorFuncMacro( ray_position[2] );
// So far we haven't accumulated anything
accum_red_intensity = 0.0;
accum_green_intensity = 0.0;
accum_blue_intensity = 0.0;
remaining_opacity = 1.0;
// Compute the increments to get to the other 7 voxel vertices from A
Binc = xinc;
Cinc = yinc;
Dinc = xinc + yinc;
Einc = zinc;
Finc = zinc + xinc;
Ginc = zinc + yinc;
Hinc = zinc + xinc + yinc;
// Compute the values for the first pass through the loop
offset = voxel[2] * zinc + voxel[1] * yinc + voxel[0];
dptr = data_ptr + offset;
nptr = encoded_normals + offset;
A = SOTF[(*(dptr))];
B = SOTF[(*(dptr + Binc))];
C = SOTF[(*(dptr + Cinc))];
D = SOTF[(*(dptr + Dinc))];
E = SOTF[(*(dptr + Einc))];
F = SOTF[(*(dptr + Finc))];
G = SOTF[(*(dptr + Ginc))];
H = SOTF[(*(dptr + Hinc))];
if ( !grad_op_is_constant )
{
goptr = grad_mag_ptr + offset;
Ago = GOTF[(*(goptr))];
Bgo = GOTF[(*(goptr + Binc))];
Cgo = GOTF[(*(goptr + Cinc))];
Dgo = GOTF[(*(goptr + Dinc))];
Ego = GOTF[(*(goptr + Einc))];
Fgo = GOTF[(*(goptr + Finc))];
Ggo = GOTF[(*(goptr + Ginc))];
Hgo = GOTF[(*(goptr + Hinc))];
}
else
{
Ago = Bgo = Cgo = Dgo = Ego = Fgo = Ggo = Hgo = 1.0;
}
// Keep track of previous voxel to know when we step into a new one
prev_voxel[0] = voxel[0];
prev_voxel[1] = voxel[1];
prev_voxel[2] = voxel[2];
// Two cases - we are working with a single color or a color transfer
// function - break them up to make it more efficient
if ( staticInfo->ColorChannels == 1 )
{
// For each step along the ray
for ( loop = 0;
loop < num_steps && remaining_opacity > VTK_REMAINING_OPACITY;
loop++ )
{
// We've taken another step
steps_this_ray++;
// Have we moved into a new voxel? If so we need to recompute A-H
if ( prev_voxel[0] != voxel[0] ||
prev_voxel[1] != voxel[1] ||
prev_voxel[2] != voxel[2] )
{
offset = voxel[2] * zinc + voxel[1] * yinc + voxel[0];
dptr = data_ptr + offset;
nptr = encoded_normals + offset;
//goptr = grad_mag_ptr + offset;
A = SOTF[(*(dptr))];
B = SOTF[(*(dptr + Binc))];
C = SOTF[(*(dptr + Cinc))];
D = SOTF[(*(dptr + Dinc))];
E = SOTF[(*(dptr + Einc))];
F = SOTF[(*(dptr + Finc))];
G = SOTF[(*(dptr + Ginc))];
H = SOTF[(*(dptr + Hinc))];
if ( !grad_op_is_constant )
{
goptr = grad_mag_ptr + offset;
Ago = GOTF[(*(goptr))];
Bgo = GOTF[(*(goptr + Binc))];
Cgo = GOTF[(*(goptr + Cinc))];
Dgo = GOTF[(*(goptr + Dinc))];
Ego = GOTF[(*(goptr + Einc))];
Fgo = GOTF[(*(goptr + Finc))];
Ggo = GOTF[(*(goptr + Ginc))];
Hgo = GOTF[(*(goptr + Hinc))];
}
else
{
Ago = Bgo = Cgo = Dgo = Ego = Fgo = Ggo = Hgo = 1.0;
}
prev_voxel[0] = voxel[0];
prev_voxel[1] = voxel[1];
prev_voxel[2] = voxel[2];
}
// Compute our offset in the voxel, and use that to trilinearly
// interpolate a value
x = ray_position[0] - (float) voxel[0];
y = ray_position[1] - (float) voxel[1];
z = ray_position[2] - (float) voxel[2];
t1 = 1.0 - x;
t2 = 1.0 - y;
t3 = 1.0 - z;
// For this sample we have do not yet have any opacity or
// shaded intensity yet
opacity = 0.0;
red_shaded_value = 0.0;
// Now add the opacity and shaded intensity value in vertex by
// vertex. If any of the A-H have a non-transparent opacity value,
// then add its contribution to the opacity
if ( A && Ago )
{
weight = t1*t2*t3 * A * Ago;
opacity += weight;
red_shaded_value += weight * ( red_d_shade[ *(nptr) ] *
GTF[*(dptr)] +
red_s_shade[ *(nptr) ] );
}
if ( B && Bgo )
{
weight = x*t2*t3 * B * Bgo;
opacity += weight;
red_shaded_value += weight * ( red_d_shade[ *(nptr + Binc) ] *
GTF[*(dptr+Binc)] +
red_s_shade[ *(nptr + Binc) ] );
}
if ( C && Cgo )
{
weight = t1*y*t3 * C * Cgo;
opacity += weight;
red_shaded_value += weight * ( red_d_shade[ *(nptr + Cinc) ] *
GTF[*(dptr+Cinc)] +
red_s_shade[ *(nptr + Cinc) ] );
}
if ( D && Dgo )
{
weight = x*y*t3 * D * Dgo;
opacity += weight;
red_shaded_value += weight * ( red_d_shade[ *(nptr + Dinc) ] *
GTF[*(dptr+Dinc)] +
red_s_shade[ *(nptr + Dinc) ] );
}
if ( E && Ego )
{
weight = t1*t2*z * E * Ego;
opacity += weight;
red_shaded_value += weight * ( red_d_shade[ *(nptr + Einc) ] *
GTF[*(dptr+Einc)] +
red_s_shade[ *(nptr + Einc) ] );
}
if ( F && Fgo )
{
weight = x*z*t2 * F * Fgo;
opacity += weight;
red_shaded_value += weight * ( red_d_shade[ *(nptr + Finc) ] *
GTF[*(dptr+Finc)] +
red_s_shade[ *(nptr + Finc) ] );
}
if ( G && Ggo )
{
weight = t1*y*z * G * Ggo;
opacity += weight;
red_shaded_value += weight * ( red_d_shade[ *(nptr + Ginc) ] *
GTF[*(dptr+Ginc)] +
red_s_shade[ *(nptr + Ginc) ] );
}
if ( H && Hgo )
{
weight = x*z*y * H * Hgo;
opacity += weight;
red_shaded_value += weight * ( red_d_shade[ *(nptr + Hinc) ] *
GTF[*(dptr+Hinc)] +
red_s_shade[ *(nptr + Hinc) ] );
}
// Accumulate intensity and opacity for this sample location
accum_red_intensity += red_shaded_value * remaining_opacity;
remaining_opacity *= (1.0 - opacity);
// Increment our position and compute our voxel location
ray_position[0] += ray_increment[0];
ray_position[1] += ray_increment[1];
ray_position[2] += ray_increment[2];
voxel[0] = vtkFloorFuncMacro( ray_position[0] );
voxel[1] = vtkFloorFuncMacro( ray_position[1] );
voxel[2] = vtkFloorFuncMacro( ray_position[2] );
}
accum_green_intensity = accum_red_intensity;
accum_blue_intensity = accum_red_intensity;
}
else if ( staticInfo->ColorChannels == 3 )
{
// For each step along the ray
for ( loop = 0;
loop < num_steps && remaining_opacity > VTK_REMAINING_OPACITY;
loop++ )
{
// We've taken another step
steps_this_ray++;
// Have we moved into a new voxel? If so we need to recompute A-H
if ( prev_voxel[0] != voxel[0] ||
prev_voxel[1] != voxel[1] ||
prev_voxel[2] != voxel[2] )
{
offset = voxel[2] * zinc + voxel[1] * yinc + voxel[0];
dptr = data_ptr + offset;
nptr = encoded_normals + offset;
A = SOTF[(*(dptr))];
B = SOTF[(*(dptr + Binc))];
C = SOTF[(*(dptr + Cinc))];
D = SOTF[(*(dptr + Dinc))];
E = SOTF[(*(dptr + Einc))];
F = SOTF[(*(dptr + Finc))];
G = SOTF[(*(dptr + Ginc))];
H = SOTF[(*(dptr + Hinc))];
if ( !grad_op_is_constant )
{
goptr = grad_mag_ptr + offset;
Ago = GOTF[(*(goptr))];
Bgo = GOTF[(*(goptr + Binc))];
Cgo = GOTF[(*(goptr + Cinc))];
Dgo = GOTF[(*(goptr + Dinc))];
Ego = GOTF[(*(goptr + Einc))];
Fgo = GOTF[(*(goptr + Finc))];
Ggo = GOTF[(*(goptr + Ginc))];
Hgo = GOTF[(*(goptr + Hinc))];
}
else
{
Ago = Bgo = Cgo = Dgo = Ego = Fgo = Ggo = Hgo = 1.0;
}
prev_voxel[0] = voxel[0];
prev_voxel[1] = voxel[1];
prev_voxel[2] = voxel[2];
}
// Compute our offset in the voxel, and use that to trilinearly
// interpolate a value
x = ray_position[0] - (float) voxel[0];
y = ray_position[1] - (float) voxel[1];
z = ray_position[2] - (float) voxel[2];
t1 = 1.0 - x;
t2 = 1.0 - y;
t3 = 1.0 - z;
// For this sample we have do not yet have any opacity or
// shaded intensity yet
opacity = 0.0;
red_shaded_value = 0.0;
green_shaded_value = 0.0;
blue_shaded_value = 0.0;
// Now add the opacity and shaded intensity value in vertex by
// vertex. If any of the A-H have a non-transparent opacity value,
// then add its contribution to the opacity
if ( A )
{
weight = t1*t2*t3 * A * Ago;
opacity += weight;
red_shaded_value += weight * ( red_d_shade[ *(nptr) ] *
CTF[*(dptr) * 3] +
red_s_shade[ *(nptr) ] );
green_shaded_value += weight * ( green_d_shade[ *(nptr) ] *
CTF[*(dptr) * 3 + 1] + +
green_s_shade[ *(nptr) ] );
blue_shaded_value += weight * ( blue_d_shade[ *(nptr) ] *
CTF[*(dptr) * 3 + 2] +
blue_s_shade[ *(nptr) ] );
}
if ( B )
{
weight = x*t2*t3 * B * Bgo;
opacity += weight;
red_shaded_value += weight * ( red_d_shade[ *(nptr + Binc) ] *
CTF[*(dptr+Binc) * 3] +
red_s_shade[ *(nptr + Binc) ] );
green_shaded_value += weight * ( green_d_shade[ *(nptr + Binc) ] *
CTF[*(dptr+Binc) * 3 + 1] +
green_s_shade[ *(nptr + Binc) ] );
blue_shaded_value += weight * ( blue_d_shade[ *(nptr + Binc) ] *
CTF[*(dptr+Binc) * 3 + 2] +
blue_s_shade[ *(nptr + Binc) ] );
}
if ( C )
{
weight = t1*y*t3 * C * Cgo;
opacity += weight;
red_shaded_value += weight * ( red_d_shade[ *(nptr + Cinc) ] *
CTF[*(dptr+Cinc) * 3] +
red_s_shade[ *(nptr + Cinc) ] );
green_shaded_value += weight * ( green_d_shade[ *(nptr + Cinc) ] *
CTF[*(dptr+Cinc) * 3 + 1] +
green_s_shade[ *(nptr + Cinc) ] );
blue_shaded_value += weight * ( blue_d_shade[ *(nptr + Cinc) ] *
CTF[*(dptr+Cinc) * 3 + 2] +
blue_s_shade[ *(nptr + Cinc) ] );
}
if ( D )
{
weight = x*y*t3 * D * Dgo;
opacity += weight;
red_shaded_value += weight * ( red_d_shade[ *(nptr + Dinc) ] *
CTF[*(dptr+Dinc) * 3] +
red_s_shade[ *(nptr + Dinc) ] );
green_shaded_value += weight * ( green_d_shade[ *(nptr + Dinc) ] *
CTF[*(dptr+Dinc) * 3 + 1] +
green_s_shade[ *(nptr + Dinc) ] );
blue_shaded_value += weight * ( blue_d_shade[ *(nptr + Dinc) ] *
CTF[*(dptr+Dinc) * 3 + 2] +
blue_s_shade[ *(nptr + Dinc) ] );
}
if ( E )
{
weight = t1*t2*z * E * Ego;
opacity += weight;
red_shaded_value += weight * ( red_d_shade[ *(nptr + Einc) ] *
CTF[*(dptr+Einc) * 3] +
red_s_shade[ *(nptr + Einc) ] );
green_shaded_value += weight * ( green_d_shade[ *(nptr + Einc) ] *
CTF[*(dptr+Einc) * 3 + 1] +
green_s_shade[ *(nptr + Einc) ] );
blue_shaded_value += weight * ( blue_d_shade[ *(nptr + Einc) ] *
CTF[*(dptr+Einc) * 3 + 2] +
blue_s_shade[ *(nptr + Einc) ] );
}
if ( F )
{
weight = x*z*t2 * F * Fgo;
opacity += weight;
red_shaded_value += weight * ( red_d_shade[ *(nptr + Finc) ] *
CTF[*(dptr+Finc) * 3] +
red_s_shade[ *(nptr + Finc) ] );
green_shaded_value += weight * ( green_d_shade[ *(nptr + Finc) ] *
CTF[*(dptr+Finc) * 3 + 1] +
green_s_shade[ *(nptr + Finc) ] );
blue_shaded_value += weight * ( blue_d_shade[ *(nptr + Finc) ] *
CTF[*(dptr+Finc) * 3 + 2] +
blue_s_shade[ *(nptr + Finc) ] );
}
if ( G )
{
weight = t1*y*z * G * Ggo;
opacity += weight;
red_shaded_value += weight * ( red_d_shade[ *(nptr + Ginc) ] *
CTF[*(dptr+Ginc) * 3] +
red_s_shade[ *(nptr + Ginc) ] );
green_shaded_value += weight * ( green_d_shade[ *(nptr + Ginc) ] *
CTF[*(dptr+Ginc) * 3 + 1] +
green_s_shade[ *(nptr + Ginc) ] );
blue_shaded_value += weight * ( blue_d_shade[ *(nptr + Ginc) ] *
CTF[*(dptr+Ginc) * 3 + 2] +
blue_s_shade[ *(nptr + Ginc) ] );
}
if ( H )
{
weight = x*z*y * H * Hgo;
opacity += weight;
red_shaded_value += weight * ( red_d_shade[ *(nptr + Hinc) ] *
CTF[*(dptr+Hinc) * 3] +
red_s_shade[ *(nptr + Hinc) ] );
green_shaded_value += weight * ( green_d_shade[ *(nptr + Hinc) ] *
CTF[*(dptr+Hinc) * 3 + 1] +
green_s_shade[ *(nptr + Hinc) ] );
blue_shaded_value += weight * ( blue_d_shade[ *(nptr + Hinc) ] *
CTF[*(dptr+Hinc) * 3 + 2] +
blue_s_shade[ *(nptr + Hinc) ] );
}
// Accumulate intensity and opacity for this sample location
accum_red_intensity += red_shaded_value * remaining_opacity;
accum_green_intensity += green_shaded_value * remaining_opacity;
accum_blue_intensity += blue_shaded_value * remaining_opacity;
remaining_opacity *= (1.0 - opacity);
// Increment our position and compute our voxel location
ray_position[0] += ray_increment[0];
ray_position[1] += ray_increment[1];
ray_position[2] += ray_increment[2];
voxel[0] = vtkFloorFuncMacro( ray_position[0] );
voxel[1] = vtkFloorFuncMacro( ray_position[1] );
voxel[2] = vtkFloorFuncMacro( ray_position[2] );
}
}
// Cap the accumulated intensity at 1.0
if ( accum_red_intensity > 1.0 )
{
accum_red_intensity = 1.0;
}
if ( accum_green_intensity > 1.0 )
{
accum_green_intensity = 1.0;
}
if ( accum_blue_intensity > 1.0 )
{
accum_blue_intensity = 1.0;
}
if( remaining_opacity < VTK_REMAINING_OPACITY )
{
remaining_opacity = 0.0;
}
// Set the return pixel value. The depth value is the distance to the
// center of the volume.
dynamicInfo->Color[0] = accum_red_intensity;
dynamicInfo->Color[1] = accum_green_intensity;
dynamicInfo->Color[2] = accum_blue_intensity;
dynamicInfo->Color[3] = 1.0 - remaining_opacity;
dynamicInfo->NumberOfStepsTaken = steps_this_ray;
}
// Constructor for the vtkVolumeRayCastCompositeFunction class
vtkVolumeRayCastCompositeFunction::vtkVolumeRayCastCompositeFunction()
{
this->CompositeMethod = VTK_COMPOSITE_INTERPOLATE_FIRST;
}
// Destruct the vtkVolumeRayCastCompositeFunction
vtkVolumeRayCastCompositeFunction::~vtkVolumeRayCastCompositeFunction()
{
}
// This is called from RenderAnImage (in vtkDepthPARCMapper.cxx)
// It uses the integer data type flag that is passed in to
// determine what type of ray needs to be cast (which is handled
// by a templated function. It also uses the shading and
// interpolation types to determine which templated function
// to call.
void vtkVolumeRayCastCompositeFunction::CastRay( vtkVolumeRayCastDynamicInfo *dynamicInfo,
vtkVolumeRayCastStaticInfo *staticInfo )
{
void *data_ptr;
data_ptr = staticInfo->ScalarDataPointer;
// Cast the ray for the data type and shading/interpolation type
if ( staticInfo->InterpolationType == VTK_NEAREST_INTERPOLATION )
{
if ( staticInfo->Shading == 0 )
{
// Nearest neighbor and no shading
switch ( staticInfo->ScalarDataType )
{
case VTK_UNSIGNED_CHAR:
vtkCastRay_NN_Unshaded( (unsigned char *)data_ptr, dynamicInfo,
staticInfo );
break;
case VTK_UNSIGNED_SHORT:
vtkCastRay_NN_Unshaded( (unsigned short *)data_ptr, dynamicInfo,
staticInfo );
break;
default:
vtkWarningMacro ( << "Unsigned char and unsigned short are the only supported datatypes for rendering" );
break;
}
}
else
{
// Nearest neighbor and shading
switch ( staticInfo->ScalarDataType )
{
case VTK_UNSIGNED_CHAR:
vtkCastRay_NN_Shaded( (unsigned char *)data_ptr, dynamicInfo, staticInfo);
break;
case VTK_UNSIGNED_SHORT:
vtkCastRay_NN_Shaded( (unsigned short *)data_ptr, dynamicInfo, staticInfo);
break;
default:
vtkWarningMacro ( << "Unsigned char and unsigned short are the only supported datatypes for rendering" );
break;
}
}
}
else
{
// Trilinear interpolation and no shading
if ( staticInfo->Shading == 0 )
{
if ( this->CompositeMethod == VTK_COMPOSITE_INTERPOLATE_FIRST )
{
switch ( staticInfo->ScalarDataType )
{
case VTK_UNSIGNED_CHAR:
vtkCastRay_TrilinSample_Unshaded( (unsigned char *)data_ptr,
dynamicInfo, staticInfo );
break;
case VTK_UNSIGNED_SHORT:
vtkCastRay_TrilinSample_Unshaded( (unsigned short *)data_ptr,
dynamicInfo, staticInfo );
break;
default:
vtkWarningMacro ( << "Unsigned char and unsigned short are the only supported datatypes for rendering" );
break;
}
}
else
{
switch ( staticInfo->ScalarDataType )
{
case VTK_UNSIGNED_CHAR:
vtkCastRay_TrilinVertices_Unshaded( (unsigned char *)data_ptr,
dynamicInfo, staticInfo );
break;
case VTK_UNSIGNED_SHORT:
vtkCastRay_TrilinVertices_Unshaded( (unsigned short *)data_ptr,
dynamicInfo, staticInfo );
break;
default:
vtkWarningMacro ( << "Unsigned char and unsigned short are the only supported datatypes for rendering" );
break;
}
}
}
else
{
// Trilinear interpolation and shading
if ( this->CompositeMethod == VTK_COMPOSITE_INTERPOLATE_FIRST )
{
switch ( staticInfo->ScalarDataType )
{
case VTK_UNSIGNED_CHAR:
vtkCastRay_TrilinSample_Shaded( (unsigned char *)data_ptr,
dynamicInfo, staticInfo );
break;
case VTK_UNSIGNED_SHORT:
vtkCastRay_TrilinSample_Shaded( (unsigned short *)data_ptr,
dynamicInfo, staticInfo );
break;
default:
vtkWarningMacro ( << "Unsigned char and unsigned short are the only supported datatypes for rendering" );
break;
}
}
else
{
switch ( staticInfo->ScalarDataType )
{
case VTK_UNSIGNED_CHAR:
vtkCastRay_TrilinVertices_Shaded( (unsigned char *)data_ptr,
dynamicInfo, staticInfo );
break;
case VTK_UNSIGNED_SHORT:
vtkCastRay_TrilinVertices_Shaded( (unsigned short *)data_ptr,
dynamicInfo, staticInfo );
break;
default:
vtkWarningMacro ( << "Unsigned char and unsigned short are the only supported datatypes for rendering" );
break;
}
}
}
}
}
float vtkVolumeRayCastCompositeFunction::GetZeroOpacityThreshold( vtkVolume
*vol )
{
return vol->GetProperty()->GetScalarOpacity()->GetFirstNonZeroValue();
}
// We don't need to do any specific initialization here...
void vtkVolumeRayCastCompositeFunction::SpecificFunctionInitialize(
vtkRenderer *vtkNotUsed(ren),
vtkVolume *vtkNotUsed(vol),
vtkVolumeRayCastStaticInfo *vtkNotUsed(staticInfo),
vtkVolumeRayCastMapper *vtkNotUsed(mapper) )
{
}
// Description:
// Return the composite method as a descriptive character string.
const char *vtkVolumeRayCastCompositeFunction::GetCompositeMethodAsString(void)
{
if( this->CompositeMethod == VTK_COMPOSITE_INTERPOLATE_FIRST )
{
return "Interpolate First";
}
if( this->CompositeMethod == VTK_COMPOSITE_CLASSIFY_FIRST )
{
return "Classify First";
}
else
{
return "Unknown";
}
}
// Print method for vtkVolumeRayCastCompositeFunction
// Since there is nothing local to print, just print the object stuff.
void vtkVolumeRayCastCompositeFunction::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os,indent);
os << indent << "Composite Method: " << this->GetCompositeMethodAsString()
<< "\n";
}