You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
744 lines
26 KiB
C++
744 lines
26 KiB
C++
/*=========================================================================
|
|
|
|
Program: Visualization Toolkit
|
|
Module: vtkFixedPointVolumeRayCastMapper.h
|
|
|
|
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.
|
|
|
|
=========================================================================*/
|
|
/**
|
|
* @class vtkFixedPointVolumeRayCastMapper
|
|
* @brief A fixed point mapper for volumes
|
|
*
|
|
* This is a software ray caster for rendering volumes in vtkImageData.
|
|
* It works with all input data types and up to four components. It performs
|
|
* composite or MIP rendering, and can be intermixed with geometric data.
|
|
* Space leaping is used to speed up the rendering process. In addition,
|
|
* calculation are performed in 15 bit fixed point precision. This mapper
|
|
* is threaded, and will interleave scan lines across processors.
|
|
*
|
|
* WARNING: This ray caster may not produce consistent results when
|
|
* the number of threads exceeds 1. The class warns if the number of
|
|
* threads > 1. The differences may be subtle. Applications should decide
|
|
* if the trade-off in performance is worth the lack of consistency.
|
|
*
|
|
* Other limitations of this ray caster include that:
|
|
* - it does not do isosurface ray casting
|
|
* - it does only interpolate before classify compositing
|
|
* - it does only maximum scalar value MIP
|
|
*
|
|
* This mapper handles all data type from unsigned char through double.
|
|
* However, some of the internal calcultions are performed in float and
|
|
* therefore even the full float range may cause problems for this mapper
|
|
* (both in scalar data values and in spacing between samples).
|
|
*
|
|
* Space leaping is performed by creating a sub-sampled volume. 4x4x4
|
|
* cells in the original volume are represented by a min, max, and
|
|
* combined gradient and flag value. The min max volume has three
|
|
* unsigned shorts per 4x4x4 group of cells from the original volume -
|
|
* one reprenting the minimum scalar index (the scalar value adjusted
|
|
* to fit in the 15 bit range), the maximum scalar index, and a
|
|
* third unsigned short which is both the maximum gradient opacity in
|
|
* the neighborhood (an unsigned char) and the flag that is filled
|
|
* in for the current lookup tables to indicate whether this region
|
|
* can be skipped.
|
|
*
|
|
* @sa
|
|
* vtkVolumeMapper
|
|
*/
|
|
|
|
#ifndef vtkFixedPointVolumeRayCastMapper_h
|
|
#define vtkFixedPointVolumeRayCastMapper_h
|
|
|
|
#include "vtkRenderingVolumeModule.h" // For export macro
|
|
#include "vtkVolumeMapper.h"
|
|
|
|
#define VTKKW_FP_SHIFT 15
|
|
#define VTKKW_FPMM_SHIFT 17
|
|
#define VTKKW_FP_MASK 0x7fff
|
|
#define VTKKW_FP_SCALE 32767.0
|
|
|
|
class vtkMatrix4x4;
|
|
class vtkMultiThreader;
|
|
class vtkPlaneCollection;
|
|
class vtkRenderer;
|
|
class vtkTimerLog;
|
|
class vtkVolume;
|
|
class vtkTransform;
|
|
class vtkRenderWindow;
|
|
class vtkColorTransferFunction;
|
|
class vtkPiecewiseFunction;
|
|
class vtkFixedPointVolumeRayCastMIPHelper;
|
|
class vtkFixedPointVolumeRayCastCompositeHelper;
|
|
class vtkFixedPointVolumeRayCastCompositeGOHelper;
|
|
class vtkFixedPointVolumeRayCastCompositeGOShadeHelper;
|
|
class vtkFixedPointVolumeRayCastCompositeShadeHelper;
|
|
class vtkVolumeRayCastSpaceLeapingImageFilter;
|
|
class vtkDirectionEncoder;
|
|
class vtkEncodedGradientShader;
|
|
class vtkFiniteDifferenceGradientEstimator;
|
|
class vtkRayCastImageDisplayHelper;
|
|
class vtkFixedPointRayCastImage;
|
|
class vtkDataArray;
|
|
|
|
// Forward declaration needed for use by friend declaration below.
|
|
VTK_THREAD_RETURN_TYPE FixedPointVolumeRayCastMapper_CastRays(void* arg);
|
|
VTK_THREAD_RETURN_TYPE vtkFPVRCMSwitchOnDataType(void* arg);
|
|
|
|
class VTKRENDERINGVOLUME_EXPORT vtkFixedPointVolumeRayCastMapper : public vtkVolumeMapper
|
|
{
|
|
public:
|
|
static vtkFixedPointVolumeRayCastMapper* New();
|
|
vtkTypeMacro(vtkFixedPointVolumeRayCastMapper, vtkVolumeMapper);
|
|
void PrintSelf(ostream& os, vtkIndent indent) override;
|
|
|
|
//@{
|
|
/**
|
|
* Set/Get the distance between samples used for rendering
|
|
* when AutoAdjustSampleDistances is off, or when this mapper
|
|
* has more than 1 second allocated to it for rendering.
|
|
*/
|
|
vtkSetMacro(SampleDistance, float);
|
|
vtkGetMacro(SampleDistance, float);
|
|
//@}
|
|
|
|
//@{
|
|
/**
|
|
* Set/Get the distance between samples when interactive rendering is happening.
|
|
* In this case, interactive is defined as this volume mapper having less than 1
|
|
* second allocated for rendering. When AutoAdjustSampleDistance is On, and the
|
|
* allocated render time is less than 1 second, then this InteractiveSampleDistance
|
|
* will be used instead of the SampleDistance above.
|
|
*/
|
|
vtkSetMacro(InteractiveSampleDistance, float);
|
|
vtkGetMacro(InteractiveSampleDistance, float);
|
|
//@}
|
|
|
|
//@{
|
|
/**
|
|
* Sampling distance in the XY image dimensions. Default value of 1 meaning
|
|
* 1 ray cast per pixel. If set to 0.5, 4 rays will be cast per pixel. If
|
|
* set to 2.0, 1 ray will be cast for every 4 (2 by 2) pixels. This value
|
|
* will be adjusted to meet a desired frame rate when AutoAdjustSampleDistances
|
|
* is on.
|
|
*/
|
|
vtkSetClampMacro(ImageSampleDistance, float, 0.1f, 100.0f);
|
|
vtkGetMacro(ImageSampleDistance, float);
|
|
//@}
|
|
|
|
//@{
|
|
/**
|
|
* This is the minimum image sample distance allow when the image
|
|
* sample distance is being automatically adjusted.
|
|
*/
|
|
vtkSetClampMacro(MinimumImageSampleDistance, float, 0.1f, 100.0f);
|
|
vtkGetMacro(MinimumImageSampleDistance, float);
|
|
//@}
|
|
|
|
//@{
|
|
/**
|
|
* This is the maximum image sample distance allow when the image
|
|
* sample distance is being automatically adjusted.
|
|
*/
|
|
vtkSetClampMacro(MaximumImageSampleDistance, float, 0.1f, 100.0f);
|
|
vtkGetMacro(MaximumImageSampleDistance, float);
|
|
//@}
|
|
|
|
//@{
|
|
/**
|
|
* If AutoAdjustSampleDistances is on, the ImageSampleDistance
|
|
* and the SampleDistance will be varied to achieve the allocated
|
|
* render time of this prop (controlled by the desired update rate
|
|
* and any culling in use). If this is an interactive render (more
|
|
* than 1 frame per second) the SampleDistance will be increased,
|
|
* otherwise it will not be altered (a binary decision, as opposed
|
|
* to the ImageSampleDistance which will vary continuously).
|
|
*/
|
|
vtkSetClampMacro(AutoAdjustSampleDistances, vtkTypeBool, 0, 1);
|
|
vtkGetMacro(AutoAdjustSampleDistances, vtkTypeBool);
|
|
vtkBooleanMacro(AutoAdjustSampleDistances, vtkTypeBool);
|
|
//@}
|
|
|
|
//@{
|
|
/**
|
|
* Automatically compute the sample distance from the data spacing. When
|
|
* the number of voxels is 8, the sample distance will be roughly 1/200
|
|
* the average voxel size. The distance will grow proportionally to
|
|
* numVoxels^(1/3) until it reaches 1/2 average voxel size when number of
|
|
* voxels is 1E6. Note that ScalarOpacityUnitDistance is still taken into
|
|
* account and if different than 1, will effect the sample distance.
|
|
*/
|
|
vtkSetClampMacro(LockSampleDistanceToInputSpacing, vtkTypeBool, 0, 1);
|
|
vtkGetMacro(LockSampleDistanceToInputSpacing, vtkTypeBool);
|
|
vtkBooleanMacro(LockSampleDistanceToInputSpacing, vtkTypeBool);
|
|
//@}
|
|
|
|
//@{
|
|
/**
|
|
* Set/Get the number of threads to use. This by default is equal to
|
|
* the number of available processors detected.
|
|
* WARNING: If number of threads > 1, results may not be consistent.
|
|
*/
|
|
void SetNumberOfThreads(int num);
|
|
int GetNumberOfThreads();
|
|
//@}
|
|
|
|
//@{
|
|
/**
|
|
* If IntermixIntersectingGeometry is turned on, the zbuffer will be
|
|
* captured and used to limit the traversal of the rays.
|
|
*/
|
|
vtkSetClampMacro(IntermixIntersectingGeometry, vtkTypeBool, 0, 1);
|
|
vtkGetMacro(IntermixIntersectingGeometry, vtkTypeBool);
|
|
vtkBooleanMacro(IntermixIntersectingGeometry, vtkTypeBool);
|
|
//@}
|
|
|
|
//@{
|
|
/**
|
|
* What is the image sample distance required to achieve the desired time?
|
|
* A version of this method is provided that does not require the volume
|
|
* argument since if you are using an LODProp3D you may not know this information.
|
|
* If you use this version you must be certain that the ray cast mapper is
|
|
* only used for one volume (and not shared among multiple volumes)
|
|
*/
|
|
float ComputeRequiredImageSampleDistance(float desiredTime, vtkRenderer* ren);
|
|
float ComputeRequiredImageSampleDistance(float desiredTime, vtkRenderer* ren, vtkVolume* vol);
|
|
//@}
|
|
|
|
/**
|
|
* WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE
|
|
* Initialize rendering for this volume.
|
|
*/
|
|
void Render(vtkRenderer*, vtkVolume*) override;
|
|
|
|
unsigned int ToFixedPointPosition(float val);
|
|
void ToFixedPointPosition(float in[3], unsigned int out[3]);
|
|
unsigned int ToFixedPointDirection(float dir);
|
|
void ToFixedPointDirection(float in[3], unsigned int out[3]);
|
|
void FixedPointIncrement(unsigned int position[3], unsigned int increment[3]);
|
|
void GetFloatTripleFromPointer(float v[3], float* ptr);
|
|
void GetUIntTripleFromPointer(unsigned int v[3], unsigned int* ptr);
|
|
void ShiftVectorDown(unsigned int in[3], unsigned int out[3]);
|
|
int CheckMinMaxVolumeFlag(unsigned int pos[3], int c);
|
|
int CheckMIPMinMaxVolumeFlag(unsigned int pos[3], int c, unsigned short maxIdx, int flip);
|
|
|
|
void LookupColorUC(unsigned short* colorTable, unsigned short* scalarOpacityTable,
|
|
unsigned short index, unsigned char color[4]);
|
|
void LookupDependentColorUC(unsigned short* colorTable, unsigned short* scalarOpacityTable,
|
|
unsigned short index[4], int components, unsigned char color[4]);
|
|
void LookupAndCombineIndependentColorsUC(unsigned short* colorTable[4],
|
|
unsigned short* scalarOpacityTable[4], unsigned short index[4], float weights[4],
|
|
int components, unsigned char color[4]);
|
|
int CheckIfCropped(unsigned int pos[3]);
|
|
|
|
vtkGetObjectMacro(RenderWindow, vtkRenderWindow);
|
|
vtkGetObjectMacro(MIPHelper, vtkFixedPointVolumeRayCastMIPHelper);
|
|
vtkGetObjectMacro(CompositeHelper, vtkFixedPointVolumeRayCastCompositeHelper);
|
|
vtkGetObjectMacro(CompositeGOHelper, vtkFixedPointVolumeRayCastCompositeGOHelper);
|
|
vtkGetObjectMacro(CompositeGOShadeHelper, vtkFixedPointVolumeRayCastCompositeGOShadeHelper);
|
|
vtkGetObjectMacro(CompositeShadeHelper, vtkFixedPointVolumeRayCastCompositeShadeHelper);
|
|
vtkGetVectorMacro(TableShift, float, 4);
|
|
vtkGetVectorMacro(TableScale, float, 4);
|
|
vtkGetMacro(ShadingRequired, int);
|
|
vtkGetMacro(GradientOpacityRequired, int);
|
|
|
|
vtkGetObjectMacro(CurrentScalars, vtkDataArray);
|
|
vtkGetObjectMacro(PreviousScalars, vtkDataArray);
|
|
|
|
int* GetRowBounds() { return this->RowBounds; }
|
|
unsigned short* GetColorTable(int c) { return this->ColorTable[c]; }
|
|
unsigned short* GetScalarOpacityTable(int c) { return this->ScalarOpacityTable[c]; }
|
|
unsigned short* GetGradientOpacityTable(int c) { return this->GradientOpacityTable[c]; }
|
|
vtkVolume* GetVolume() { return this->Volume; }
|
|
unsigned short** GetGradientNormal() { return this->GradientNormal; }
|
|
unsigned char** GetGradientMagnitude() { return this->GradientMagnitude; }
|
|
unsigned short* GetDiffuseShadingTable(int c) { return this->DiffuseShadingTable[c]; }
|
|
unsigned short* GetSpecularShadingTable(int c) { return this->SpecularShadingTable[c]; }
|
|
|
|
void ComputeRayInfo(
|
|
int x, int y, unsigned int pos[3], unsigned int dir[3], unsigned int* numSteps);
|
|
|
|
void InitializeRayInfo(vtkVolume* vol);
|
|
|
|
int ShouldUseNearestNeighborInterpolation(vtkVolume* vol);
|
|
|
|
//@{
|
|
/**
|
|
* Set / Get the underlying image object. One will be automatically
|
|
* created - only need to set it when using from an AMR mapper which
|
|
* renders multiple times into the same image.
|
|
*/
|
|
void SetRayCastImage(vtkFixedPointRayCastImage*);
|
|
vtkGetObjectMacro(RayCastImage, vtkFixedPointRayCastImage);
|
|
//@}
|
|
|
|
int PerImageInitialization(vtkRenderer*, vtkVolume*, int, double*, double*, int*);
|
|
void PerVolumeInitialization(vtkRenderer*, vtkVolume*);
|
|
void PerSubVolumeInitialization(vtkRenderer*, vtkVolume*, int);
|
|
void RenderSubVolume();
|
|
void DisplayRenderedImage(vtkRenderer*, vtkVolume*);
|
|
void AbortRender();
|
|
|
|
void CreateCanonicalView(vtkVolume* volume, vtkImageData* image, int blend_mode,
|
|
double viewDirection[3], double viewUp[3]);
|
|
|
|
/**
|
|
* Get an estimate of the rendering time for a given volume / renderer.
|
|
* Only valid if this mapper has been used to render that volume for
|
|
* that renderer previously. Estimate is good when the viewing parameters
|
|
* have not changed much since that last render.
|
|
*/
|
|
float GetEstimatedRenderTime(vtkRenderer* ren, vtkVolume* vol)
|
|
{
|
|
return this->RetrieveRenderTime(ren, vol);
|
|
}
|
|
float GetEstimatedRenderTime(vtkRenderer* ren) { return this->RetrieveRenderTime(ren); }
|
|
|
|
//@{
|
|
/**
|
|
* Set/Get the window / level applied to the final color.
|
|
* This allows brightness / contrast adjustments on the
|
|
* final image.
|
|
* window is the width of the window.
|
|
* level is the center of the window.
|
|
* Initial window value is 1.0
|
|
* Initial level value is 0.5
|
|
* window cannot be null but can be negative, this way
|
|
* values will be reversed.
|
|
* |window| can be larger than 1.0
|
|
* level can be any real value.
|
|
*/
|
|
vtkSetMacro(FinalColorWindow, float);
|
|
vtkGetMacro(FinalColorWindow, float);
|
|
vtkSetMacro(FinalColorLevel, float);
|
|
vtkGetMacro(FinalColorLevel, float);
|
|
//@}
|
|
|
|
// Here to be used by the mapper to tell the helper
|
|
// to flip the MIP comparison in order to support
|
|
// minimum intensity blending
|
|
vtkGetMacro(FlipMIPComparison, int);
|
|
|
|
/**
|
|
* WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE
|
|
* Release any graphics resources that are being consumed by this mapper.
|
|
* The parameter window could be used to determine which graphic
|
|
* resources to release.
|
|
*/
|
|
void ReleaseGraphicsResources(vtkWindow*) override;
|
|
|
|
protected:
|
|
vtkFixedPointVolumeRayCastMapper();
|
|
~vtkFixedPointVolumeRayCastMapper() override;
|
|
|
|
// The helper class that displays the image
|
|
vtkRayCastImageDisplayHelper* ImageDisplayHelper;
|
|
|
|
// The distance between sample points along the ray
|
|
float SampleDistance;
|
|
float InteractiveSampleDistance;
|
|
|
|
// The distance between rays in the image
|
|
float ImageSampleDistance;
|
|
float MinimumImageSampleDistance;
|
|
float MaximumImageSampleDistance;
|
|
vtkTypeBool AutoAdjustSampleDistances;
|
|
vtkTypeBool LockSampleDistanceToInputSpacing;
|
|
|
|
// Saved values used to restore
|
|
float OldSampleDistance;
|
|
float OldImageSampleDistance;
|
|
|
|
// Internal method for computing matrices needed during
|
|
// ray casting
|
|
void ComputeMatrices(double volumeOrigin[3], double volumeSpacing[3], int volumeExtent[6],
|
|
vtkRenderer* ren, vtkVolume* vol);
|
|
|
|
int ComputeRowBounds(vtkRenderer* ren, int imageFlag, int rowBoundsFlag, int volumeExtent[6]);
|
|
|
|
void CaptureZBuffer(vtkRenderer* ren);
|
|
|
|
friend VTK_THREAD_RETURN_TYPE FixedPointVolumeRayCastMapper_CastRays(void* arg);
|
|
friend VTK_THREAD_RETURN_TYPE vtkFPVRCMSwitchOnDataType(void* arg);
|
|
|
|
vtkMultiThreader* Threader;
|
|
|
|
vtkMatrix4x4* PerspectiveMatrix;
|
|
vtkMatrix4x4* ViewToWorldMatrix;
|
|
vtkMatrix4x4* ViewToVoxelsMatrix;
|
|
vtkMatrix4x4* VoxelsToViewMatrix;
|
|
vtkMatrix4x4* WorldToVoxelsMatrix;
|
|
vtkMatrix4x4* VoxelsToWorldMatrix;
|
|
|
|
vtkMatrix4x4* VolumeMatrix;
|
|
|
|
vtkTransform* PerspectiveTransform;
|
|
vtkTransform* VoxelsTransform;
|
|
vtkTransform* VoxelsToViewTransform;
|
|
|
|
// This object encapsulated the image and all related information
|
|
vtkFixedPointRayCastImage* RayCastImage;
|
|
|
|
int* RowBounds;
|
|
int* OldRowBounds;
|
|
|
|
float* RenderTimeTable;
|
|
vtkVolume** RenderVolumeTable;
|
|
vtkRenderer** RenderRendererTable;
|
|
int RenderTableSize;
|
|
int RenderTableEntries;
|
|
|
|
void StoreRenderTime(vtkRenderer* ren, vtkVolume* vol, float t);
|
|
float RetrieveRenderTime(vtkRenderer* ren, vtkVolume* vol);
|
|
float RetrieveRenderTime(vtkRenderer* ren);
|
|
|
|
vtkTypeBool IntermixIntersectingGeometry;
|
|
|
|
float MinimumViewDistance;
|
|
|
|
vtkColorTransferFunction* SavedRGBFunction[4];
|
|
vtkPiecewiseFunction* SavedGrayFunction[4];
|
|
vtkPiecewiseFunction* SavedScalarOpacityFunction[4];
|
|
vtkPiecewiseFunction* SavedGradientOpacityFunction[4];
|
|
int SavedColorChannels[4];
|
|
float SavedScalarOpacityDistance[4];
|
|
int SavedBlendMode;
|
|
vtkImageData* SavedParametersInput;
|
|
vtkTimeStamp SavedParametersMTime;
|
|
|
|
vtkImageData* SavedGradientsInput;
|
|
vtkTimeStamp SavedGradientsMTime;
|
|
|
|
float SavedSampleDistance;
|
|
|
|
unsigned short ColorTable[4][32768 * 3];
|
|
unsigned short ScalarOpacityTable[4][32768];
|
|
unsigned short GradientOpacityTable[4][256];
|
|
int TableSize[4];
|
|
float TableScale[4];
|
|
float TableShift[4];
|
|
|
|
float GradientMagnitudeScale[4];
|
|
float GradientMagnitudeShift[4];
|
|
|
|
unsigned short** GradientNormal;
|
|
unsigned char** GradientMagnitude;
|
|
unsigned short* ContiguousGradientNormal;
|
|
unsigned char* ContiguousGradientMagnitude;
|
|
|
|
int NumberOfGradientSlices;
|
|
|
|
vtkDirectionEncoder* DirectionEncoder;
|
|
|
|
vtkEncodedGradientShader* GradientShader;
|
|
|
|
vtkFiniteDifferenceGradientEstimator* GradientEstimator;
|
|
|
|
unsigned short DiffuseShadingTable[4][65536 * 3];
|
|
unsigned short SpecularShadingTable[4][65536 * 3];
|
|
|
|
int ShadingRequired;
|
|
int GradientOpacityRequired;
|
|
|
|
vtkDataArray* CurrentScalars;
|
|
vtkDataArray* PreviousScalars;
|
|
|
|
vtkRenderWindow* RenderWindow;
|
|
vtkVolume* Volume;
|
|
|
|
int ClipRayAgainstVolume(
|
|
float rayStart[3], float rayEnd[3], float rayDirection[3], double bounds[6]);
|
|
|
|
int UpdateColorTable(vtkVolume* vol);
|
|
int UpdateGradients(vtkVolume* vol);
|
|
int UpdateShadingTable(vtkRenderer* ren, vtkVolume* vol);
|
|
void UpdateCroppingRegions();
|
|
|
|
void ComputeGradients(vtkVolume* vol);
|
|
|
|
int ClipRayAgainstClippingPlanes(
|
|
float rayStart[3], float rayEnd[3], int numClippingPlanes, float* clippingPlanes);
|
|
|
|
unsigned int FixedPointCroppingRegionPlanes[6];
|
|
unsigned int CroppingRegionMask[27];
|
|
|
|
// Get the ZBuffer value corresponding to location (x,y) where (x,y)
|
|
// are indexing into the ImageInUse image. This must be converted to
|
|
// the zbuffer image coordinates. Nearest neighbor value is returned.
|
|
float GetZBufferValue(int x, int y);
|
|
|
|
vtkFixedPointVolumeRayCastMIPHelper* MIPHelper;
|
|
vtkFixedPointVolumeRayCastCompositeHelper* CompositeHelper;
|
|
vtkFixedPointVolumeRayCastCompositeGOHelper* CompositeGOHelper;
|
|
vtkFixedPointVolumeRayCastCompositeShadeHelper* CompositeShadeHelper;
|
|
vtkFixedPointVolumeRayCastCompositeGOShadeHelper* CompositeGOShadeHelper;
|
|
|
|
// Some variables used for ray computation
|
|
float ViewToVoxelsArray[16];
|
|
float WorldToVoxelsArray[16];
|
|
float VoxelsToWorldArray[16];
|
|
|
|
double CroppingBounds[6];
|
|
|
|
int NumTransformedClippingPlanes;
|
|
float* TransformedClippingPlanes;
|
|
|
|
double SavedSpacing[3];
|
|
|
|
// Min Max structure used to do space leaping
|
|
unsigned short* MinMaxVolume;
|
|
int MinMaxVolumeSize[4];
|
|
vtkImageData* SavedMinMaxInput;
|
|
vtkImageData* MinMaxVolumeCache;
|
|
vtkVolumeRayCastSpaceLeapingImageFilter* SpaceLeapFilter;
|
|
|
|
void UpdateMinMaxVolume(vtkVolume* vol);
|
|
void FillInMaxGradientMagnitudes(int fullDim[3], int smallDim[3]);
|
|
|
|
float FinalColorWindow;
|
|
float FinalColorLevel;
|
|
|
|
int FlipMIPComparison;
|
|
|
|
void ApplyFinalColorWindowLevel();
|
|
|
|
private:
|
|
vtkFixedPointVolumeRayCastMapper(const vtkFixedPointVolumeRayCastMapper&) = delete;
|
|
void operator=(const vtkFixedPointVolumeRayCastMapper&) = delete;
|
|
|
|
bool ThreadWarning;
|
|
};
|
|
|
|
inline unsigned int vtkFixedPointVolumeRayCastMapper::ToFixedPointPosition(float val)
|
|
{
|
|
return static_cast<unsigned int>(val * VTKKW_FP_SCALE + 0.5);
|
|
}
|
|
|
|
inline void vtkFixedPointVolumeRayCastMapper::ToFixedPointPosition(float in[3], unsigned int out[3])
|
|
{
|
|
out[0] = static_cast<unsigned int>(in[0] * VTKKW_FP_SCALE + 0.5);
|
|
out[1] = static_cast<unsigned int>(in[1] * VTKKW_FP_SCALE + 0.5);
|
|
out[2] = static_cast<unsigned int>(in[2] * VTKKW_FP_SCALE + 0.5);
|
|
}
|
|
|
|
inline unsigned int vtkFixedPointVolumeRayCastMapper::ToFixedPointDirection(float dir)
|
|
{
|
|
return ((dir < 0.0) ? (static_cast<unsigned int>(-dir * VTKKW_FP_SCALE + 0.5))
|
|
: (0x80000000 + static_cast<unsigned int>(dir * VTKKW_FP_SCALE + 0.5)));
|
|
}
|
|
|
|
inline void vtkFixedPointVolumeRayCastMapper::ToFixedPointDirection(
|
|
float in[3], unsigned int out[3])
|
|
{
|
|
out[0] = ((in[0] < 0.0) ? (static_cast<unsigned int>(-in[0] * VTKKW_FP_SCALE + 0.5))
|
|
: (0x80000000 + static_cast<unsigned int>(in[0] * VTKKW_FP_SCALE + 0.5)));
|
|
out[1] = ((in[1] < 0.0) ? (static_cast<unsigned int>(-in[1] * VTKKW_FP_SCALE + 0.5))
|
|
: (0x80000000 + static_cast<unsigned int>(in[1] * VTKKW_FP_SCALE + 0.5)));
|
|
out[2] = ((in[2] < 0.0) ? (static_cast<unsigned int>(-in[2] * VTKKW_FP_SCALE + 0.5))
|
|
: (0x80000000 + static_cast<unsigned int>(in[2] * VTKKW_FP_SCALE + 0.5)));
|
|
}
|
|
|
|
inline void vtkFixedPointVolumeRayCastMapper::FixedPointIncrement(
|
|
unsigned int position[3], unsigned int increment[3])
|
|
{
|
|
if (increment[0] & 0x80000000)
|
|
{
|
|
position[0] += (increment[0] & 0x7fffffff);
|
|
}
|
|
else
|
|
{
|
|
position[0] -= increment[0];
|
|
}
|
|
if (increment[1] & 0x80000000)
|
|
{
|
|
position[1] += (increment[1] & 0x7fffffff);
|
|
}
|
|
else
|
|
{
|
|
position[1] -= increment[1];
|
|
}
|
|
if (increment[2] & 0x80000000)
|
|
{
|
|
position[2] += (increment[2] & 0x7fffffff);
|
|
}
|
|
else
|
|
{
|
|
position[2] -= increment[2];
|
|
}
|
|
}
|
|
|
|
inline void vtkFixedPointVolumeRayCastMapper::GetFloatTripleFromPointer(float v[3], float* ptr)
|
|
{
|
|
v[0] = *(ptr);
|
|
v[1] = *(ptr + 1);
|
|
v[2] = *(ptr + 2);
|
|
}
|
|
|
|
inline void vtkFixedPointVolumeRayCastMapper::GetUIntTripleFromPointer(
|
|
unsigned int v[3], unsigned int* ptr)
|
|
{
|
|
v[0] = *(ptr);
|
|
v[1] = *(ptr + 1);
|
|
v[2] = *(ptr + 2);
|
|
}
|
|
|
|
inline void vtkFixedPointVolumeRayCastMapper::ShiftVectorDown(
|
|
unsigned int in[3], unsigned int out[3])
|
|
{
|
|
out[0] = in[0] >> VTKKW_FP_SHIFT;
|
|
out[1] = in[1] >> VTKKW_FP_SHIFT;
|
|
out[2] = in[2] >> VTKKW_FP_SHIFT;
|
|
}
|
|
|
|
inline int vtkFixedPointVolumeRayCastMapper::CheckMinMaxVolumeFlag(unsigned int mmpos[3], int c)
|
|
{
|
|
vtkIdType offset = static_cast<vtkIdType>(this->MinMaxVolumeSize[3]) *
|
|
(mmpos[2] * static_cast<vtkIdType>(this->MinMaxVolumeSize[0] * this->MinMaxVolumeSize[1]) +
|
|
mmpos[1] * static_cast<vtkIdType>(this->MinMaxVolumeSize[0]) + mmpos[0]) +
|
|
static_cast<vtkIdType>(c);
|
|
|
|
return ((*(this->MinMaxVolume + 3 * offset + 2)) & 0x00ff);
|
|
}
|
|
|
|
inline int vtkFixedPointVolumeRayCastMapper::CheckMIPMinMaxVolumeFlag(
|
|
unsigned int mmpos[3], int c, unsigned short maxIdx, int flip)
|
|
{
|
|
vtkIdType offset = static_cast<vtkIdType>(this->MinMaxVolumeSize[3]) *
|
|
(mmpos[2] * static_cast<vtkIdType>(this->MinMaxVolumeSize[0] * this->MinMaxVolumeSize[1]) +
|
|
mmpos[1] * static_cast<vtkIdType>(this->MinMaxVolumeSize[0]) + mmpos[0]) +
|
|
static_cast<vtkIdType>(c);
|
|
|
|
if ((*(this->MinMaxVolume + 3 * offset + 2) & 0x00ff))
|
|
{
|
|
if (flip)
|
|
{
|
|
return (*(this->MinMaxVolume + 3 * offset) < maxIdx);
|
|
}
|
|
else
|
|
{
|
|
return (*(this->MinMaxVolume + 3 * offset + 1) > maxIdx);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
inline void vtkFixedPointVolumeRayCastMapper::LookupColorUC(unsigned short* colorTable,
|
|
unsigned short* scalarOpacityTable, unsigned short index, unsigned char color[4])
|
|
{
|
|
unsigned short alpha = scalarOpacityTable[index];
|
|
color[0] = static_cast<unsigned char>(
|
|
(colorTable[3 * index] * alpha + 0x7fff) >> (2 * VTKKW_FP_SHIFT - 8));
|
|
color[1] = static_cast<unsigned char>(
|
|
(colorTable[3 * index + 1] * alpha + 0x7fff) >> (2 * VTKKW_FP_SHIFT - 8));
|
|
color[2] = static_cast<unsigned char>(
|
|
(colorTable[3 * index + 2] * alpha + 0x7fff) >> (2 * VTKKW_FP_SHIFT - 8));
|
|
color[3] = static_cast<unsigned char>(alpha >> (VTKKW_FP_SHIFT - 8));
|
|
}
|
|
|
|
inline void vtkFixedPointVolumeRayCastMapper::LookupDependentColorUC(unsigned short* colorTable,
|
|
unsigned short* scalarOpacityTable, unsigned short index[4], int components,
|
|
unsigned char color[4])
|
|
{
|
|
unsigned short alpha;
|
|
switch (components)
|
|
{
|
|
case 2:
|
|
alpha = scalarOpacityTable[index[1]];
|
|
color[0] = static_cast<unsigned char>(
|
|
(colorTable[3 * index[0]] * alpha + 0x7fff) >> (2 * VTKKW_FP_SHIFT - 8));
|
|
color[1] = static_cast<unsigned char>(
|
|
(colorTable[3 * index[0] + 1] * alpha + 0x7fff) >> (2 * VTKKW_FP_SHIFT - 8));
|
|
color[2] = static_cast<unsigned char>(
|
|
(colorTable[3 * index[0] + 2] * alpha + 0x7fff) >> (2 * VTKKW_FP_SHIFT - 8));
|
|
color[3] = static_cast<unsigned char>(alpha >> (VTKKW_FP_SHIFT - 8));
|
|
break;
|
|
case 4:
|
|
alpha = scalarOpacityTable[index[3]];
|
|
color[0] = static_cast<unsigned char>((index[0] * alpha + 0x7fff) >> VTKKW_FP_SHIFT);
|
|
color[1] = static_cast<unsigned char>((index[1] * alpha + 0x7fff) >> VTKKW_FP_SHIFT);
|
|
color[2] = static_cast<unsigned char>((index[2] * alpha + 0x7fff) >> VTKKW_FP_SHIFT);
|
|
color[3] = static_cast<unsigned char>(alpha >> (VTKKW_FP_SHIFT - 8));
|
|
break;
|
|
}
|
|
}
|
|
|
|
inline void vtkFixedPointVolumeRayCastMapper::LookupAndCombineIndependentColorsUC(
|
|
unsigned short* colorTable[4], unsigned short* scalarOpacityTable[4], unsigned short index[4],
|
|
float weights[4], int components, unsigned char color[4])
|
|
{
|
|
unsigned int tmp[4] = { 0, 0, 0, 0 };
|
|
|
|
for (int i = 0; i < components; i++)
|
|
{
|
|
unsigned short alpha =
|
|
static_cast<unsigned short>(static_cast<float>(scalarOpacityTable[i][index[i]]) * weights[i]);
|
|
tmp[0] += static_cast<unsigned char>(
|
|
((colorTable[i][3 * index[i]]) * alpha + 0x7fff) >> (2 * VTKKW_FP_SHIFT - 8));
|
|
tmp[1] += static_cast<unsigned char>(
|
|
((colorTable[i][3 * index[i] + 1]) * alpha + 0x7fff) >> (2 * VTKKW_FP_SHIFT - 8));
|
|
tmp[2] += static_cast<unsigned char>(
|
|
((colorTable[i][3 * index[i] + 2]) * alpha + 0x7fff) >> (2 * VTKKW_FP_SHIFT - 8));
|
|
tmp[3] += static_cast<unsigned char>(alpha >> (VTKKW_FP_SHIFT - 8));
|
|
}
|
|
|
|
color[0] = static_cast<unsigned char>((tmp[0] > 255) ? (255) : (tmp[0]));
|
|
color[1] = static_cast<unsigned char>((tmp[1] > 255) ? (255) : (tmp[1]));
|
|
color[2] = static_cast<unsigned char>((tmp[2] > 255) ? (255) : (tmp[2]));
|
|
color[3] = static_cast<unsigned char>((tmp[3] > 255) ? (255) : (tmp[3]));
|
|
}
|
|
|
|
inline int vtkFixedPointVolumeRayCastMapper::CheckIfCropped(unsigned int pos[3])
|
|
{
|
|
int idx;
|
|
|
|
if (pos[2] < this->FixedPointCroppingRegionPlanes[4])
|
|
{
|
|
idx = 0;
|
|
}
|
|
else if (pos[2] > this->FixedPointCroppingRegionPlanes[5])
|
|
{
|
|
idx = 18;
|
|
}
|
|
else
|
|
{
|
|
idx = 9;
|
|
}
|
|
|
|
if (pos[1] >= this->FixedPointCroppingRegionPlanes[2])
|
|
{
|
|
if (pos[1] > this->FixedPointCroppingRegionPlanes[3])
|
|
{
|
|
idx += 6;
|
|
}
|
|
else
|
|
{
|
|
idx += 3;
|
|
}
|
|
}
|
|
|
|
if (pos[0] >= this->FixedPointCroppingRegionPlanes[0])
|
|
{
|
|
if (pos[0] > this->FixedPointCroppingRegionPlanes[1])
|
|
{
|
|
idx += 2;
|
|
}
|
|
else
|
|
{
|
|
idx += 1;
|
|
}
|
|
}
|
|
|
|
return !(static_cast<unsigned int>(this->CroppingRegionFlags) & this->CroppingRegionMask[idx]);
|
|
}
|
|
|
|
#endif
|