Commit f8c5c678 authored by Dave DeMarle's avatar Dave DeMarle
Browse files

Add render mode in which values are drawn as recoverable 24bit colors.

With this you can pick an array component and draw that directly
on the screen. Afterward, if you know the min and max, you read pixel
values back and get a hold of the value at each pixel.

TODO:
* Lots of type conversion here, and in the end only using 24 bits
of resolution. When and if we need more accuracy, flesh out
the extensible conversion operator part.
* Surface selection is based on the same concept (ident buffer)
but that was written before VTK has extensible rendering (painters
and passes). Eventually selection should be reimplemented to use
this.
* Would be great to demonstrate render into background followed by
mouse overs.

Change-Id: I44608759278c37c8250f957d596f3f4149382bbb
parent 386cfd4f
......@@ -286,7 +286,7 @@ void vtkPainterPolyDataMapper::RenderPiece(vtkRenderer* ren, vtkActor* act)
// FIXME: This is not supported currently for composite datasets.
vtkInformationVector *inArrayVec =
this->Information->Get(INPUT_ARRAYS_TO_PROCESS());
int numArrays = inArrayVec->GetNumberOfInformationObjects();
int numArrays = (inArrayVec?inArrayVec->GetNumberOfInformationObjects():0);
for(int i = 0; i < numArrays; i++)
{
......
......@@ -47,6 +47,7 @@ include(vtkObjectFactory)
set(Module_SRCS
vtkCameraPass.cxx
vtkClearRGBPass.cxx
vtkClearZPass.cxx
vtkColorMaterialHelper.cxx
vtkDataTransferHelper.cxx
......@@ -104,6 +105,9 @@ set(Module_SRCS
vtkTextureUnitManager.cxx
vtkTranslucentPass.cxx
vtkUniformVariables.cxx
vtkValuePainter.cxx
vtkValuePass.cxx
vtkValuePasses.cxx
vtkVolumetricPass.cxx
${CMAKE_CURRENT_BINARY_DIR}/vtkgl.cxx
${CMAKE_CURRENT_BINARY_DIR}/vtkRenderingOpenGLObjectFactory.cxx
......
......@@ -13,6 +13,8 @@ vtk_add_test_cxx(${vtk-module}CxxTests render_window_tests
TestScalarsToColorsPainter.cxx
TestSetImageOrientation.cxx
TestTDx.cxx
TestValuePainter.cxx,NO_VALID
TestValuePasses.cxx
)
vtk_add_test_cxx(${vtk-module}CxxTests render_window_tests
TestBlurAndSobelPasses.cxx
......
/*=========================================================================
Program: Visualization Toolkit
Module: TestBlurAndSobelPasses.cxx
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.
=========================================================================*/
// This test covers the ability for the value painter to draw arrays as
// colors such that the visible values can be recovered from the pixels.
#include <vtkActor.h>
#include <vtkCellArray.h>
#include <vtkCellData.h>
#include <vtkDoubleArray.h>
#include <vtkMath.h>
#include <vtkPointData.h>
#include <vtkPoints.h>
#include <vtkPolyData.h>
#include <vtkPainterPolyDataMapper.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkSmartPointer.h>
#include <vtkValuePainter.h>
#include <vtkWindowToImageFilter.h>
#include <set>
#define MAX 10
void PrepArray(bool byName, bool drawCell, int arrayIndex, int arrayComponent,
vtkDataSet *dataset, vtkDataArray *values, vtkValuePainter *painter,
double *&minmax)
{
if (drawCell)
{
if (arrayIndex > dataset->GetCellData()->GetNumberOfArrays())
{
arrayIndex = 0;
}
values = dataset->GetCellData()->GetArray(arrayIndex);
if (arrayComponent > values->GetNumberOfComponents())
{
arrayComponent = 0;
}
cerr << "Drawing " << values->GetName() << " [" << arrayComponent << "]" << endl;
if (!byName)
{
painter->SetInputArrayToProcess(VTK_SCALAR_MODE_USE_CELL_FIELD_DATA, arrayIndex);
}
else
{
painter->SetInputArrayToProcess(VTK_SCALAR_MODE_USE_CELL_FIELD_DATA, values->GetName());
}
minmax = values->GetRange(arrayComponent);
}
else
{
if (arrayIndex > dataset->GetPointData()->GetNumberOfArrays())
{
arrayIndex = 0;
}
values = dataset->GetPointData()->GetArray(arrayIndex);
if (arrayComponent > values->GetNumberOfComponents())
{
arrayComponent = 0;
}
cerr << "Drawing " << values->GetName() << " [" << arrayComponent << "]" << endl;
if (!byName)
{
painter->SetInputArrayToProcess(VTK_SCALAR_MODE_USE_POINT_FIELD_DATA, arrayIndex);
}
else
{
painter->SetInputArrayToProcess(VTK_SCALAR_MODE_USE_POINT_FIELD_DATA, values->GetName());
}
minmax = values->GetRange(arrayComponent);
}
}
int TestValuePainter(int argc, char* argv[])
{
bool byName = true;
bool drawCell = true;
unsigned int arrayIndex = 0;
unsigned int arrayComponent = 0;
bool interactive = false;
for (int i = 0; i < argc; i++)
{
if (!strcmp(argv[i],"index"))
{
byName = false;
}
if (!strcmp(argv[i],"point"))
{
drawCell = false;
}
if (!strcmp(argv[i],"N"))
{
arrayIndex = atoi(argv[i+1]);
}
if (!strcmp(argv[i],"C"))
{
arrayComponent = atoi(argv[i+1]);
}
if (!strcmp(argv[i],"-I"))
{
interactive = true;
}
}
/*
vtkSmartPointer<vtkXMLPolyDataReader> reader = vtkSmartPointer<vtkXMLPolyDataReader>::New();
reader->SetFileName("/Source/CINEMA/value-painter/vtkexample/data/test.vtp");
reader->Update();
*/
vtkSmartPointer<vtkPolyData> dataset = vtkSmartPointer<vtkPolyData>::New();
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
dataset->SetPoints(points);
vtkSmartPointer<vtkDoubleArray> scalars = vtkSmartPointer<vtkDoubleArray>::New();
scalars->SetNumberOfComponents(1);
scalars->SetName("Point Scalar Array 1");
dataset->GetPointData()->AddArray(scalars);
vtkSmartPointer<vtkDoubleArray> vectors = vtkSmartPointer<vtkDoubleArray>::New();
vectors->SetNumberOfComponents(3);
vectors->SetName("Point Vector Array 1");
dataset->GetPointData()->AddArray(vectors);
double vector[3];
for (unsigned int i = 0; i < MAX; i++)
{
for (unsigned int j = 0; j < MAX; j++)
{
points->InsertNextPoint(i,j,0.0);
scalars->InsertNextValue((double)i/MAX+10);
vector[0] = sin((double)j/MAX*6.1418);
vector[1] = 1.0;
vector[2] = 1.0;
vtkMath::Normalize(vector);
vectors->InsertNextTuple3(vector[0],vector[1],vector[2]);
}
}
vtkSmartPointer<vtkCellArray> cells = vtkSmartPointer<vtkCellArray>::New();
dataset->SetPolys(cells);
scalars = vtkSmartPointer<vtkDoubleArray>::New();
scalars->SetNumberOfComponents(1);
scalars->SetName("Cell Scalar Array 1");
dataset->GetCellData()->AddArray(scalars);
vectors = vtkSmartPointer<vtkDoubleArray>::New();
vectors->SetNumberOfComponents(3);
vectors->SetName("Cell Vector Array 1");
dataset->GetCellData()->AddArray(vectors);
for (unsigned int i = 0; i < (MAX-1); i++)
{
for (unsigned int j = 0; j < (MAX-1); j++)
{
cells->InsertNextCell(4);
cells->InsertCellPoint(i*MAX +j);
cells->InsertCellPoint(i*MAX +j+1);
cells->InsertCellPoint((i+1)*MAX+j+1);
cells->InsertCellPoint((i+1)*MAX+j);
scalars->InsertNextValue((double)i/(MAX-1)-10);
vector[0] = sin((double)j/(MAX-1)*6.1418);
vector[1] = 1.0;
vector[2] = 1.0;
vtkMath::Normalize(vector);
vectors->InsertNextTuple3(vector[0],vector[1],vector[2]);
}
}
vtkSmartPointer<vtkPainterPolyDataMapper> mapper =
vtkSmartPointer<vtkPainterPolyDataMapper>::New();
mapper->SetInputData(dataset);
mapper->SetScalarModeToUsePointData();
mapper->SelectColorArray(0);
vtkSmartPointer<vtkValuePainter> painter = vtkSmartPointer<vtkValuePainter>::New();
vtkDataArray *values = NULL;
double *minmax;
PrepArray(byName, drawCell, arrayIndex, arrayComponent,
dataset, values, painter,
minmax);
double scale = minmax[1]-minmax[0];
painter->SetInputComponentToProcess(arrayComponent);
mapper->SetPainter(painter);
vtkSmartPointer<vtkActor> actor =
vtkSmartPointer<vtkActor>::New();
actor->SetMapper(mapper);
vtkSmartPointer<vtkRenderer> renderer =
vtkSmartPointer<vtkRenderer>::New();
//manually set background to the "nothing" color
renderer->SetBackground(0.0,0.0,0.0);
renderer->GradientBackgroundOff();
vtkSmartPointer<vtkRenderWindow> renderWindow =
vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->AddRenderer(renderer);
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
renderWindowInteractor->SetRenderWindow(renderWindow);
renderer->AddActor(actor);
renderWindow->Render();
//iterate to look for leaks and such
for (int i = 0; i < 8; i++)
{
bool _byName = true;
bool _drawCell = true;
vtkFieldData *fd = dataset->GetCellData();
if (i<4)
{
_byName = false;
}
if (i%2)
{
_drawCell = false;
fd = dataset->GetPointData();
}
for (int j = 0; j < fd->GetNumberOfArrays(); j++)
{
for (int k = 0; k < fd->GetArray(j)->GetNumberOfComponents(); k++)
{
PrepArray(_byName, _drawCell, j, k, dataset, values, painter, minmax);
renderWindow->Render();
}
}
}
PrepArray(byName, drawCell, arrayIndex, arrayComponent,
dataset, values, painter,
minmax);
renderWindow->Render();
vtkSmartPointer<vtkWindowToImageFilter> grabber = vtkSmartPointer<vtkWindowToImageFilter>::New();
grabber->SetInput(renderWindow);
grabber->Update();
vtkImageData *id = grabber->GetOutput();
//id->PrintSelf(cerr, vtkIndent(0));
vtkUnsignedCharArray *ar = vtkUnsignedCharArray::SafeDownCast(id->GetPointData()->GetArray("ImageScalars"));
unsigned char *ptr = static_cast<unsigned char*>(ar->GetVoidPointer(0));
std::set<double> found;
double value;
for (unsigned int i = 0; i < id->GetNumberOfPoints(); i++)
{
vtkValuePainter::ColorToValue(ptr, minmax[0], scale, value);
if (found.find(value)==found.end())
{
found.insert(value);
cerr << "READ "
<< std::hex
<< (int) ptr[0] << (int) ptr[1] << (int) ptr[2] << "\t"
<< std::dec
<< value << endl;
}
ptr+=3;
}
std::set<double>::iterator it;
double min = VTK_DOUBLE_MAX;
double max = VTK_DOUBLE_MIN;
for (it = found.begin(); it != found.end(); ++it)
{
if (*it < min)
{
min = *it;
}
if (*it > max)
{
max = *it;
}
}
bool fail = false;
if (fabs(min - -10.0) > 0.12)
{
cerr << "ERROR min value not correct" << endl;
fail = true;
}
if (fabs(max - -9.0) > 0.12)
{
cerr << "ERROR max value not correct" << endl;
fail = true;
}
if (interactive)
{
renderWindowInteractor->Start();
}
return fail;
}
/*=========================================================================
Program: Visualization Toolkit
Module: TestValuePasses.cxx
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.
=========================================================================*/
// This test covers rendering a scene using ValuePasses to draw arrays as
// decipherable colors. In interactive mode, hit the 'c' key to cycle
// between standard and value rendered colormaps.
//
// The command line arguments are:
// -I => run in interactive mode; unless this is used, the program will
// not allow interaction and exit
#include "vtkTestUtilities.h"
#include "vtkRegressionTestImage.h"
#include "vtkActor.h"
#include "vtkCamera.h"
#include "vtkCameraPass.h"
#include "vtkCellData.h"
#include "vtkDataSetSurfaceFilter.h"
#include "vtkDefaultPass.h"
#include "vtkDataSetAttributes.h"
#include "vtkElevationFilter.h"
#include "vtkImageData.h"
#include "vtkImageDataGeometryFilter.h"
#include "vtkImageSinusoidSource.h"
#include "vtkInformation.h"
#include "vtkInteractorEventRecorder.h"
#include "vtkInteractorStyleTrackballCamera.h"
#include "vtkLookupTable.h"
#include "vtkObjectFactory.h"
#include "vtkOpenGLExtensionManager.h"
#include "vtkOpenGLRenderer.h"
#include "vtkOpenGLRenderWindow.h"
#include "vtkPointData.h"
#include "vtkPointDataToCellData.h"
#include "vtkPolyDataMapper.h"
#include "vtkRenderPassCollection.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkSmartPointer.h"
#include "vtkValuePasses.h"
#include "vtkValuePainter.h"
#include "vtkCameraPass.h"
#include "vtkDefaultPass.h"
#include "vtkLightsPass.h"
#include "vtkRenderPassCollection.h"
#include "vtkSequencePass.h"
vtkProp * prop = NULL;
const char TestValuePassesEventLog[] =
"# StreamVersion 1\n"
"LeftButtonPressEvent 148 258 0 0 0 0 0\n"
"StartInteractionEvent 148 258 0 0 0 0 0\n"
"KeyPressEvent 177 231 0 0 99 1 c\n"
"CharEvent 177 231 0 0 99 1 c\n"
"KeyReleaseEvent 177 231 0 0 99 1 c\n"
"KeyPressEvent 177 231 0 0 99 1 c\n"
"CharEvent 177 231 0 0 99 1 c\n"
"KeyReleaseEvent 177 231 0 0 99 1 c\n"
"KeyPressEvent 177 231 0 0 99 1 c\n"
"CharEvent 177 231 0 0 99 1 c\n"
"KeyReleaseEvent 177 231 0 0 99 1 c\n"
"KeyPressEvent 177 231 0 0 97 1 a\n"
"CharEvent 177 231 0 0 97 1 a\n"
"KeyReleaseEvent 177 231 0 0 97 1 a\n"
"KeyPressEvent 177 231 0 0 97 1 a\n"
"CharEvent 177 231 0 0 97 1 a\n"
"KeyReleaseEvent 177 231 0 0 97 1 a\n"
"KeyPressEvent 177 231 0 0 97 1 a\n"
"CharEvent 177 231 0 0 97 1 a\n"
"KeyReleaseEvent 177 231 0 0 97 1 a\n"
"KeyPressEvent 177 231 0 0 97 1 a\n"
"CharEvent 177 231 0 0 97 1 a\n"
"KeyReleaseEvent 177 231 0 0 97 1 a\n"
"KeyPressEvent 177 231 0 0 97 1 a\n"
"CharEvent 177 231 0 0 97 1 a\n"
"KeyReleaseEvent 177 231 0 0 97 1 a\n"
;
// Define interaction style
class KeyPressInteractorStyle : public vtkInteractorStyleTrackballCamera
{
private:
vtkOpenGLRenderer *GLRenderer;
vtkRenderPass *VCamera;
vtkRenderPass *Values;
vtkRenderPass *NormalC;
vtkAlgorithm *Alg;
unsigned int Counter;
public:
static KeyPressInteractorStyle* New();
vtkTypeMacro(KeyPressInteractorStyle, vtkInteractorStyleTrackballCamera);
KeyPressInteractorStyle()
{
this->Counter = 0;
this->SetPipelineControlPoints(NULL,NULL,NULL,NULL,NULL);
}
void SetPipelineControlPoints(vtkOpenGLRenderer *g,
vtkRenderPass *vc,
vtkRenderPass *v,
vtkRenderPass *n,
vtkAlgorithm *p)
{
this->GLRenderer = g;
this->VCamera = vc;
this->Values = v;
this->NormalC = n;
this->Alg = p;
}
virtual void OnKeyPress()
{
if (this->GLRenderer == NULL)
{
return;
}
// Get the keypress
vtkRenderWindowInteractor *rwi = this->Interactor;
std::string key = rwi->GetKeySym();
if(key == "c")
{
vtkRenderPass * current = this->GLRenderer->GetPass();
if (current == NULL)
{
cerr << "Value (multipass) rendering" << endl;
this->GLRenderer->SetPass(this->VCamera);
this->GLRenderer->GetRenderWindow()->Render();
}
else if (current == this->VCamera)
{
cerr << "Normal (multipass) rendering" << endl;
this->GLRenderer->SetPass(this->NormalC);
this->GLRenderer->GetRenderWindow()->Render();
}
else if (current == this->NormalC)
{
cerr << "Hardcoded rendering" << endl;
this->GLRenderer->SetPass(NULL);
this->GLRenderer->GetRenderWindow()->Render();
}
}
if(key == "a")
{
vtkRenderPass * current = this->GLRenderer->GetPass();
if (current == this->VCamera)
{
vtkDataSet *ds = vtkDataSet::SafeDownCast(this->Alg->GetOutputDataObject(0));
if (ds)
{
#define DO_INFO
#ifdef DO_INFO
cerr << "Change array through actor's info" << endl;
#else
cerr << "Change array through passes' API" << endl;
#endif
this->Counter++;
unsigned int na = 0;
vtkFieldData *fd;
fd = ds->GetPointData();
for (int i = 0; i < fd->GetNumberOfArrays(); i++)
{
na += fd->GetArray(i)->GetNumberOfComponents();
}
fd = ds->GetCellData();
for (int i = 0; i < fd->GetNumberOfArrays(); i++)
{
na += fd->GetArray(i)->GetNumberOfComponents();
}
int c = this->Counter % na;
int mode;
int a = -1;
for (int f = 0; f < 2; f++)
{
if (f == 0)
{
mode = VTK_SCALAR_MODE_USE_POINT_FIELD_DATA;
fd = ds->GetPointData();
}
else
{
mode = VTK_SCALAR_MODE_USE_CELL_FIELD_DATA;
fd = ds->GetCellData();
}
for (int i = 0; i < fd->GetNumberOfArrays(); i++)
{
vtkDataArray *array = fd->GetArray(i);
for (int j = 0; j < array->GetNumberOfComponents(); j++)
{
a++;
if (c == a)
{
cerr << "Draw " << ((mode == VTK_SCALAR_MODE_USE_POINT_FIELD_DATA)?"point ":"cell ")
<< i << "," << j << " " << fd->GetArray(i)->GetName() << endl;
#ifdef DO_INFO
//send it via information keys
vtkInformation *iv = vtkInformation::New();
iv->Set(vtkValuePainter::SCALAR_MODE(), mode);
# if 1
iv->Set(vtkValuePainter::ARRAY_NAME(), fd->GetArray(i)->GetName()); //by names
# else
iv->Set(vtkValuePainter::ARRAY_ID(), i); //by index
# endif
iv->Set(vtkValuePainter::ARRAY_COMPONENT(), j);
prop->SetPropertyKeys(iv);
iv->Delete();
#else
//use direct access to the renderpass API
vtkValuePasses *vp = (vtkValuePasses*)this->Values;
vp->SetInputArrayToProcess(mode, i);
vp->SetInputComponentToProcess(j);
#endif
}
}
}
}
this->GLRenderer->GetRenderWindow()->Render();
}
}
}
// Forward events
vtkInteractorStyleTrackballCamera::OnKeyPress();
}
};