Skip to content

Commit 5d8e8d5

Browse files
committed
Added texture width checks in opacity and gradientOpacity tables.
ColorTransferFunction and PiecewiseFunction estimate an appropriate number of samples based on a given range and minimum distance between nodes. This estimated value is used by the volume lookup tables to sample the functions into the texture.
1 parent ddb5ebc commit 5d8e8d5

10 files changed

+532
-256
lines changed

Common/DataModel/vtkPiecewiseFunction.cxx

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,37 @@ int vtkPiecewiseFunction::AdjustRange(double range[2])
682682
return 1;
683683
}
684684

685+
//--------------------------------------------------------------------------
686+
int vtkPiecewiseFunction::EstimateMinNumberOfSamples(double const & x1,
687+
double const & x2)
688+
{
689+
double const d = this->FindMinimumXDistance();
690+
int idealWidth = static_cast<int>(ceil((x2 - x1) / d));
691+
692+
return idealWidth;
693+
}
694+
695+
//----------------------------------------------------------------------------
696+
double vtkPiecewiseFunction::FindMinimumXDistance()
697+
{
698+
std::vector<vtkPiecewiseFunctionNode*> const & nodes = this->Internal->Nodes;
699+
size_t const size = nodes.size();
700+
if (size < 2)
701+
return -1.0;
702+
703+
double distance = std::numeric_limits<double>::max();
704+
for (size_t i = 0; i < size - 1; i++)
705+
{
706+
double const currentDist = nodes[i + 1]->X - nodes[i]->X;
707+
if (currentDist < distance)
708+
{
709+
distance = currentDist;
710+
}
711+
}
712+
713+
return distance;
714+
}
715+
685716
// Returns a table of function values evaluated at regular intervals
686717
void vtkPiecewiseFunction::GetTable( double xStart, double xEnd,
687718
int size, double* table,

Common/DataModel/vtkPiecewiseFunction.h

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -165,10 +165,26 @@ class VTKCOMMONDATAMODEL_EXPORT vtkPiecewiseFunction : public vtkDataObject
165165
vtkGetMacro(AllowDuplicateScalars, int);
166166
vtkBooleanMacro(AllowDuplicateScalars, int);
167167

168+
// Description:
169+
// Estimates the minimum size of a table such that it would correctly sample this function.
170+
// The returned value should be passed as parameter 'n' when calling GetTable().
171+
int EstimateMinNumberOfSamples(double const & x1, double const & x2);
172+
168173
protected:
169174
vtkPiecewiseFunction();
170175
~vtkPiecewiseFunction();
171176

177+
// Internal method to sort the vector and update the
178+
// Range whenever a node is added, edited or removed.
179+
// It always calls Modified().
180+
void SortAndUpdateRange();
181+
// Returns true if the range has been updated and Modified() has been called
182+
bool UpdateRange();
183+
184+
// Description:
185+
// Traverses the nodes to find the minimum distance. Assumes nodes are sorted.
186+
double FindMinimumXDistance();
187+
172188
// The internal STL structures
173189
vtkPiecewiseFunctionInternals *Internal;
174190

@@ -184,13 +200,6 @@ class VTKCOMMONDATAMODEL_EXPORT vtkPiecewiseFunction : public vtkDataObject
184200
// Min and max range of function point locations
185201
double Range[2];
186202

187-
// Internal method to sort the vector and update the
188-
// Range whenever a node is added, edited or removed.
189-
// It always calls Modified().
190-
void SortAndUpdateRange();
191-
// Returns true if the range has been updated and Modified() has been called
192-
bool UpdateRange();
193-
194203
int AllowDuplicateScalars;
195204

196205
private:

Rendering/Core/vtkColorTransferFunction.cxx

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1835,6 +1835,16 @@ int vtkColorTransferFunction::AdjustRange(double range[2])
18351835
return 1;
18361836
}
18371837

1838+
//--------------------------------------------------------------------------
1839+
int vtkColorTransferFunction::EstimateMinNumberOfSamples(double const & x1,
1840+
double const & x2)
1841+
{
1842+
double const d = this->FindMinimumXDistance();
1843+
int idealWidth = static_cast<int>(ceil((x2 - x1) / d));
1844+
1845+
return idealWidth;
1846+
}
1847+
18381848
//----------------------------------------------------------------------------
18391849
double vtkColorTransferFunction::FindMinimumXDistance()
18401850
{
@@ -1844,11 +1854,9 @@ double vtkColorTransferFunction::FindMinimumXDistance()
18441854
return -1.0;
18451855

18461856
double distance = std::numeric_limits<double>::max();
1847-
18481857
for (size_t i = 0; i < size - 1; i++)
18491858
{
1850-
double const currentDist = nodes.at(i + 1)->X - nodes.at(i)->X;
1851-
1859+
double const currentDist = nodes[i + 1]->X - nodes[i]->X;
18521860
if (currentDist < distance)
18531861
{
18541862
distance = currentDist;

Rendering/Core/vtkColorTransferFunction.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -247,8 +247,9 @@ class VTKRENDERINGCORE_EXPORT vtkColorTransferFunction : public vtkScalarsToColo
247247
virtual void GetIndexedColor(vtkIdType idx, double rgba[4]);
248248

249249
// Description:
250-
// Traverses the nodes to find the minimum distance. Assumes nodes are sorted.
251-
double FindMinimumXDistance();
250+
// Estimates the minimum size of a table such that it would correctly sample this function.
251+
// The returned value should be passed as parameter 'n' when calling GetTable().
252+
int EstimateMinNumberOfSamples(double const & x1, double const & x2);
252253

253254
protected:
254255
vtkColorTransferFunction();
@@ -341,6 +342,10 @@ class VTKRENDERINGCORE_EXPORT vtkColorTransferFunction : public vtkScalarsToColo
341342
// any point existed at newX, it will also be removed.
342343
void MovePoint(double oldX, double newX);
343344

345+
// Description:
346+
// Traverses the nodes to find the minimum distance. Assumes nodes are sorted.
347+
double FindMinimumXDistance();
348+
344349
private:
345350
vtkColorTransferFunction(const vtkColorTransferFunction&) VTK_DELETE_FUNCTION;
346351
void operator=(const vtkColorTransferFunction&) VTK_DELETE_FUNCTION;

Rendering/Volume/Testing/Cxx/TestGPURayCastLargeColorTransferFunction.cxx

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "vtkCamera.h"
1919
#include "vtkColorTransferFunction.h"
2020
#include "vtkGPUVolumeRayCastMapper.h"
21+
#include "vtkFixedPointVolumeRayCastMapper.h"
2122
#include "vtkImageData.h"
2223
#include "vtkLookupTable.h"
2324
#include "vtkPiecewiseFunction.h"
@@ -33,6 +34,9 @@
3334
#include "vtkVolumeProperty.h"
3435
#include "vtkXMLImageDataReader.h"
3536

37+
38+
#define GPU_MAPPER
39+
3640
//----------------------------------------------------------------------------
3741
int TestGPURayCastLargeColorTransferFunction(int argc, char* argv[])
3842
{
@@ -43,8 +47,16 @@ int TestGPURayCastLargeColorTransferFunction(int argc, char* argv[])
4347
// http://www.spl.harvard.edu/publications/item/view/2037
4448
vtkSmartPointer<vtkLookupTable> lut =
4549
vtkSmartPointer<vtkLookupTable>::New();
46-
lut->SetNumberOfTableValues(5023);
47-
lut->SetTableRange(0, 5022);
50+
51+
// Required for vtkLookupTable initialization
52+
int const NumValues = 5023;
53+
lut->SetNumberOfTableValues(NumValues);
54+
lut->SetTableRange(0, NumValues-1);
55+
for (int i = 0; i < NumValues; i++)
56+
{
57+
lut->SetTableValue(i, 0.0, 0.0, 0.0, 0.0);
58+
}
59+
4860
lut->SetTableValue(0, 0 / 255.0, 0 / 255.0, 0 / 255.0, 0 / 255.0);
4961
lut->SetTableValue(2, 250 / 255.0, 250 / 255.0, 225 / 255.0, 255 / 255.0);
5062
lut->SetTableValue(3, 225 / 255.0, 190 / 255.0, 150 / 255.0, 255 / 255.0);
@@ -80,7 +92,8 @@ int TestGPURayCastLargeColorTransferFunction(int argc, char* argv[])
8092
lut->SetTableValue(54, 98 / 255.0, 153 / 255.0, 112 / 255.0, 255 / 255.0);
8193
lut->SetTableValue(58, 165 / 255.0, 0 / 255.0, 255 / 255.0, 255 / 255.0);
8294
lut->SetTableValue(60, 165 / 255.0, 40 / 255.0, 40 / 255.0, 255 / 255.0);
83-
lut->SetTableValue(61, 135 / 255.0, 205 / 255.0, 235 / 255.0, 255 / 255.0);
95+
// lut->SetTableValue(61, 165 / 255.0, 40 / 255.0, 40 / 255.0, 255 / 255.0);
96+
lut->SetTableValue(61, 135 / 255.0, 205 / 255.0, 235 / 255.0, 255 / 255.0); //medulla oblongata
8497
lut->SetTableValue(63, 90 / 255.0, 105 / 255.0, 215 / 255.0, 255 / 255.0);
8598
lut->SetTableValue(66, 0 / 255.0, 108 / 255.0, 112 / 255.0, 255 / 255.0);
8699
lut->SetTableValue(71, 0 / 255.0, 108 / 255.0, 112 / 255.0, 255 / 255.0);
@@ -393,6 +406,7 @@ int TestGPURayCastLargeColorTransferFunction(int argc, char* argv[])
393406
const double midPoint = 0.5;
394407
const double sharpness = 1.0;
395408
for (int i = 0; i < numColors; i++, value += step)
409+
// for (int i = 0; i < numColors; i++, value += (50 * step) )
396410
{
397411
lut->GetTableValue(i, color);
398412

@@ -412,16 +426,22 @@ int TestGPURayCastLargeColorTransferFunction(int argc, char* argv[])
412426
delete [] filename;
413427
filename = NULL;
414428

429+
#ifdef GPU_MAPPER
415430
vtkSmartPointer<vtkGPUVolumeRayCastMapper> volumeMapper =
416431
vtkSmartPointer<vtkGPUVolumeRayCastMapper>::New();
432+
#else
433+
vtkSmartPointer<vtkFixedPointVolumeRayCastMapper> volumeMapper =
434+
vtkSmartPointer<vtkFixedPointVolumeRayCastMapper>::New();
435+
#endif
436+
417437
volumeMapper->SetInputData(reader->GetOutput());
418438

419439
vtkSmartPointer<vtkVolumeProperty> volumeProperty =
420440
vtkSmartPointer<vtkVolumeProperty>::New();
421441
volumeProperty->SetColor(colorTransferFunction);
422442
volumeProperty->SetScalarOpacity(opacity);
423443
volumeProperty->SetInterpolationTypeToNearest();
424-
volumeProperty->ShadeOn();
444+
// volumeProperty->ShadeOn();
425445
volumeProperty->SetAmbient(0.3);
426446
volumeProperty->SetDiffuse(0.6);
427447
volumeProperty->SetSpecular(0.5);
@@ -437,6 +457,7 @@ int TestGPURayCastLargeColorTransferFunction(int argc, char* argv[])
437457
xf->RotateZ(180.0);
438458
xf->RotateY(25.0);
439459
xf->RotateX(-65.0);
460+
//xf->RotateY(-90.0);
440461
volume->SetUserTransform(xf);
441462

442463
vtkSmartPointer<vtkRenderWindow> renderWindow =
@@ -460,7 +481,11 @@ int TestGPURayCastLargeColorTransferFunction(int argc, char* argv[])
460481
iren->SetRenderWindow(renderWindow);
461482
renderWindow->Render();// make sure we have an OpenGL context.
462483

484+
#ifdef GPU_MAPPER
463485
int valid = volumeMapper->IsRenderSupported(renderWindow, volumeProperty);
486+
#else
487+
int valid = 1;
488+
#endif
464489

465490
int retVal;
466491
if (valid)

0 commit comments

Comments
 (0)