Skip to content

Commit

Permalink
Merge pull request #53 from visit-dav/task/maguire7/2019_01_default_v…
Browse files Browse the repository at this point in the history
…olume_renderer

Task/maguire7/2019 01 default volume renderer
  • Loading branch information
Alister committed Feb 6, 2019
2 parents cf40022 + 30ac9c4 commit 70b6d9c
Show file tree
Hide file tree
Showing 99 changed files with 395 additions and 295 deletions.
2 changes: 1 addition & 1 deletion src/plots/Volume/Volume.xml
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@
true
</Field>
<Field name="resampleTarget" label="resampleTarget" type="int">
50000
1000000
</Field>
<Field name="opacityVariable" label="opacityVariable" type="variablename" vartypes="01000000000">
default
Expand Down
2 changes: 1 addition & 1 deletion src/plots/Volume/VolumeAttributes.C
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ void VolumeAttributes::Init()
opacityAttenuation = 1;
opacityMode = FreeformMode;
resampleFlag = true;
resampleTarget = 50000;
resampleTarget = 1000000;
for(int i = 0; i < 256; ++i)
freeformOpacity[i] = (unsigned char)i;
useColorVarMin = false;
Expand Down
203 changes: 136 additions & 67 deletions src/plots/Volume/avtDefaultRenderer.C
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,14 @@
#include <vtkRectilinearGrid.h>
#include <vtkUnstructuredGrid.h>
#include <vtkRenderer.h>
#include <vtkVolumeProperty.h>
#include <vtkImageData.h>
#include <vtkSmartVolumeMapper.h>

#include <VolumeAttributes.h>
#include <avtCallback.h>
#include <DebugStream.h>

#include <vtkColorTransferFunction.h>
#include <vtkVolumeProperty.h>
#include <vtkImageData.h>
#include <vtkPiecewiseFunction.h>

#ifndef NO_DATA_VALUE
#define NO_DATA_VALUE -1e+37
Expand Down Expand Up @@ -81,12 +80,17 @@

avtDefaultRenderer::avtDefaultRenderer()
{
VTKRen = NULL;
curVolume = NULL;
imageToRender = NULL;
resetColorMap = false;
volumeProp = vtkSmartPointer<vtkVolumeProperty>::New();
mapper = vtkSmartPointer<vtkSmartVolumeMapper>::New();
VTKRen = NULL;
imageToRender = NULL;

volumeProp = vtkVolumeProperty::New();
mapper = vtkSmartVolumeMapper::New();
curVolume = vtkVolume::New();
transFunc = vtkColorTransferFunction::New();
opacity = vtkPiecewiseFunction::New();

resetColorMap = false;
useInterpolation = true;
}


Expand All @@ -101,10 +105,38 @@ avtDefaultRenderer::avtDefaultRenderer()
//
// Modifications:
//
// Alister Maguire, Tue Dec 11 10:18:31 PST 2018
// Added deletions for curVolume, imageToRender, volumeProp,
// and mapper.
//
// ****************************************************************************

avtDefaultRenderer::~avtDefaultRenderer()
{
if (curVolume != NULL)
{
curVolume->Delete();
}
if (imageToRender != NULL)
{
imageToRender->Delete();
}
if (volumeProp != NULL)
{
volumeProp->Delete();
}
if (mapper != NULL)
{
mapper->Delete();
}
if (transFunc != NULL)
{
transFunc->Delete();
}
if (opacity != NULL)
{
opacity->Delete();
}
}


Expand All @@ -123,30 +155,39 @@ avtDefaultRenderer::~avtDefaultRenderer()
//
// Modifications:
//
// Alister Maguire, Tue Dec 11 13:02:20 PST 2018
// Refactored to appropriately handle the NO_DATA_VALUE. Also
// changed smart pointers to standard pointers and added memory
// management.
//
// ****************************************************************************

void
avtDefaultRenderer::Render(
const avtVolumeRendererImplementation::RenderProperties &props,
const avtVolumeRendererImplementation::VolumeData &volume)
{
bool needsReset = false;
const char *mName = "avtDefaultRenderer::Render: ";

//2D data has no volume, so we don't try to render this.
//
// 2D data has no volume, so we don't try to render this.
//
if (props.dataIs2D)
{
debug5 << mName << "Cannot perform volume rendering on "
<< "2D data... returning" << endl;
return;
}

if(imageToRender == NULL)
if (imageToRender == NULL)
{
debug5 << mName << "Converting from rectilinear grid "
<< "to image data" << endl;

//Need to create a vtkImageData object to feed into the mapper.
//
// Our mapper requires a vtkImageData as input. We must
// create one.
//
int dims[3], extent[6];
((vtkRectilinearGrid *)volume.grid)->GetDimensions(dims);
((vtkRectilinearGrid *)volume.grid)->GetExtent(extent);
Expand All @@ -161,31 +202,46 @@ avtDefaultRenderer::Render(
double spacingZ = rgrid->GetZCoordinates()->GetTuple1(1)-
rgrid->GetZCoordinates()->GetTuple1(0);

imageToRender = vtkSmartPointer<vtkImageData>::New();
imageToRender = vtkImageData::New();
imageToRender->SetDimensions(dims);
imageToRender->SetExtent(extent);
imageToRender->SetSpacing(spacingX, spacingY, spacingZ);
imageToRender->AllocateScalars(VTK_FLOAT, 1);
int limit = dims[0] * dims[1] * dims[2];

//Set the origin to match the lower bounds of the grid
//
// Set the origin to match the lower bounds of the grid
//
double bounds[6];
((vtkRectilinearGrid *)volume.grid)->GetBounds(bounds);
imageToRender->SetOrigin(bounds[0], bounds[2], bounds[4]);

float magnitude = volume.data.max - volume.data.min;

//We need to transfer the rgrid data over to the image data,
//but we also need to scale the values to a range that opengl
//can handle.
float *scalarP = (float *)imageToRender->GetScalarPointer();
for (int i = 0 ; i < limit ; i++)
int nScalars = dims[0] * dims[1] * dims[2];
float *scalarP = (float *)imageToRender->GetScalarPointer();

//
// We need to transfer the rgrid data over to the image data
// and scale to the proper range.
// VisIt populates empty space with the NO_DATA_VALUE.
// We need to map this to a value that our mapper accepts,
// and then clamp it out of vision.
//
for (int i = 0 ; i < nScalars; i++)
{
float tuple1 = dataArr->GetTuple1(i);
if (tuple1 <= NO_DATA_VALUE)
scalarP[i] = -1.0;//just below our color map
{
//
// Our color map is 0 -> 255. For no data values,
// assign a new value just out side of the map.
//
scalarP[i] = -1.0;
useInterpolation = false;
}
else
scalarP[i] = ((255*(tuple1-volume.data.min))/magnitude);
{
scalarP[i] = ((255.0 * (tuple1 - volume.data.min)) / magnitude);
}
}

debug5 << mName << "Adding data to the SmartVolumeMapper" << endl;
Expand All @@ -194,80 +250,93 @@ avtDefaultRenderer::Render(
mapper->SetScalarModeToUsePointData();
mapper->SetBlendModeToComposite();
resetColorMap = true;
needsReset = true;
}

if(resetColorMap || oldAtts != props.atts)
if (resetColorMap || oldAtts != props.atts)
{

debug5 << mName << "Resetting color" << endl;

//Getting color/alpha transfer function from VisIt
//
// Getting color/alpha transfer function from VisIt
//
unsigned char rgba[256*4];
props.atts.GetTransferFunction(rgba);

vtkSmartPointer<vtkColorTransferFunction> transFunc =
vtkSmartPointer<vtkColorTransferFunction>::New();
vtkSmartPointer<vtkPiecewiseFunction> opacity =
vtkSmartPointer<vtkPiecewiseFunction>::New();

//We don't want to see the default values, so we turn clamping
//off (opacity becomes 0.0)
//
// We don't want to see the no data values, so we turn clamping
// off (opacity becomes 0.0)
//
transFunc->SetScaleToLinear();
transFunc->SetClamping(0);
opacity->SetClamping(0);

float atten = props.atts.GetOpacityAttenuation()/256.f;
float atten = props.atts.GetOpacityAttenuation() / 255.f;

//Add the color map to vtk's transfer function
//
// Add the color map to vtk's transfer function
//
for(int i = 0; i < 256; i++)
{
int rgbIdx = 4*i;
float curOp = rgba[rgbIdx+3]*atten;
transFunc->AddRGBPoint(i, rgba[rgbIdx]/255.f, rgba[rgbIdx+1]/255.f,
rgba[rgbIdx+2]/255.f);
int rgbIdx = 4 * i;
float curOp = rgba[rgbIdx + 3] * atten;
transFunc->AddRGBPoint(i, rgba[rgbIdx] / 255.f,
rgba[rgbIdx + 1] / 255.f,
rgba[rgbIdx + 2] / 255.f);
opacity->AddPoint(i, MAX(0.0, MIN(1.0, curOp)));
}

//For some reason, the endpoints aren't included when clamping
//is turned off. So, let's put some padding on the ends of our
//mapping functions.
//
// For some reason, the endpoints aren't included when clamping
// is turned off. So, let's put some padding on the ends of our
// mapping functions.
//
int lastIdx = 255*4;
transFunc->AddRGBPoint(-1, rgba[0]/255.f, rgba[1]/255.f,
rgba[2]/255.f);
transFunc->AddRGBPoint(256, rgba[lastIdx]/255.f, rgba[lastIdx+1]/255.f,
rgba[lastIdx+2]/255.f);
opacity->AddPoint(-1, rgba[3]*atten);
opacity->AddPoint(256, rgba[lastIdx+3]*atten);

//Set the volume properties
transFunc->AddRGBPoint(-1, rgba[0] / 255.f,
rgba[1] / 255.f,
rgba[2] / 255.f);
transFunc->AddRGBPoint(256, rgba[lastIdx] / 255.f,
rgba[lastIdx + 1] / 255.f,
rgba[lastIdx + 2] / 255.f);
opacity->AddPoint(-1, rgba[3] * atten);
opacity->AddPoint(256, rgba[lastIdx + 3] * atten);

//
// Set the volume properties.
//
if (props.atts.GetLightingFlag())
{
volumeProp->SetShade(1);
}
else
{
volumeProp->SetShade(0);
}

volumeProp->SetScalarOpacity(opacity);
volumeProp->SetColor(transFunc);
volumeProp->SetInterpolationType(VTK_LINEAR_INTERPOLATION);

//
// If our dataset contains NO_DATA_VALUEs, interpolation will
// not work correctly on the boundaries (between a real value and
// a no data value). Hopefully this will be addressed in the
// future. For now, we only interpolate when our dataset contains
// none of these values.
//
if (useInterpolation)
{
volumeProp->SetInterpolationTypeToLinear();
}
else
{
volumeProp->SetInterpolationTypeToNearest();
}

resetColorMap = false;
needsReset = true;
oldAtts = props.atts;
}

debug5 << mName << "Checking if volume needs to be updated" << endl;

//Create the volume to be rendered and
//set its mapper to our SmartVolumeMapper.
if (curVolume == NULL || needsReset)
{
debug5 << mName << "Updating the volume!" << endl;

curVolume = vtkSmartPointer<vtkVolume>::New();
curVolume->SetMapper(mapper);
curVolume->SetProperty(volumeProp);
}

debug5 << mName << "Rendering!" << endl;

mapper->Render(VTKRen, curVolume);
}
30 changes: 19 additions & 11 deletions src/plots/Volume/avtDefaultRenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,10 @@
#include <avtVolumeRendererImplementation.h>
#include <VolumeAttributes.h>

#include <vtkSmartPointer.h>
#include <vtkVolume.h>
#include <vtkSmartVolumeMapper.h>
#include <vtkColorTransferFunction.h>
#include <vtkPiecewiseFunction.h>

// ****************************************************************************
// Class: avtDefaultRenderer
Expand All @@ -62,27 +63,34 @@
// Creation: April 3, 2017
//
// Modifications:
//
// Alister Maguire, Tue Dec 11 10:18:31 PST 2018
// Changed pointers to standard instead of smart.
// Added transfer function and opacity.
//
// ****************************************************************************

class avtDefaultRenderer : public avtVolumeRendererImplementation
{
public:
avtDefaultRenderer();
virtual ~avtDefaultRenderer();
avtDefaultRenderer();
virtual ~avtDefaultRenderer();

protected:
virtual void Render(const RenderProperties &props,
const VolumeData &volume);
virtual void Render(const RenderProperties &props,
const VolumeData &volume);

vtkSmartPointer<vtkVolume> curVolume;
vtkSmartPointer<vtkImageData> imageToRender;
vtkSmartPointer<vtkVolumeProperty> volumeProp;
vtkSmartPointer<vtkSmartVolumeMapper> mapper;
vtkColorTransferFunction *transFunc;
vtkPiecewiseFunction *opacity;
vtkVolume *curVolume;
vtkImageData *imageToRender;
vtkVolumeProperty *volumeProp;
vtkSmartVolumeMapper *mapper;

VolumeAttributes oldAtts;
VolumeAttributes oldAtts;

bool resetColorMap;
bool resetColorMap;
bool useInterpolation;
};

#endif

0 comments on commit 70b6d9c

Please sign in to comment.