Commit 47988961 authored by Will Schroeder's avatar Will Schroeder

New filter to convert depth image to point cloud

This filter takes a depth image and optional color image
and produces a point cloud. It has been threaded (vtkSMPTools)
for performance. It plays nicely with vtkRendererSource.

Regression test images; xform working

Properly testing two image inputs

Cleaned ArrayListTemplate API

Regression test images

Tests vary depending on OpenGL backend

Provide more code coverage

Reflect VTK_DELETE_FUNCTION
parent 4a25e5c6
......@@ -208,7 +208,7 @@ struct ArrayList;
template <typename T>
void CreateArrayPair(ArrayList *list, T *inData, T *outData,
vtkIdType numPts, int numComp, T nullValue);
vtkIdType numTuples, int numComp, T nullValue);
// A list of the arrays to interpolate, and a method to invoke interpolation on the list
......@@ -226,7 +226,7 @@ struct ArrayList
// Add a pair of arrays (manual insertion). Returns the output array created,
// if any. No array may be created if \c inArray was previously marked as
// excluded using ExcludeArray().
vtkDataArray* AddArrayPair(vtkIdType numPts, vtkDataArray *inArray,
vtkDataArray* AddArrayPair(vtkIdType numTuples, vtkDataArray *inArray,
vtkStdString &outArrayName, double nullValue, bool promote);
// Any array excluded here is not added by AddArrays() or AddArrayPair, hence not
......
......@@ -24,20 +24,24 @@
// Sort of a little object factory (in conjunction w/ vtkTemplateMacro())
template <typename T>
void CreateArrayPair(ArrayList *list, T *inData, T *outData,
vtkIdType numPts, int numComp, vtkDataArray *outArray, T nullValue)
vtkIdType numTuples, int numComp, vtkDataArray *outArray,
T nullValue)
{
ArrayPair<T> *pair = new ArrayPair<T>(inData,outData,numPts,numComp,outArray,nullValue);
ArrayPair<T> *pair = new ArrayPair<T>(inData,outData,numTuples,numComp,
outArray,nullValue);
list->Arrays.push_back(pair);
}
//----------------------------------------------------------------------------
// Sort of a little object factory (in conjunction w/ vtkTemplateMacro())
template <typename T>
void CreateRealArrayPair(ArrayList *list, T *inData, float *outData,vtkIdType numPts,
int numComp, vtkDataArray *outArray, float nullValue)
void CreateRealArrayPair(ArrayList *list, T *inData, float *outData,
vtkIdType numTuples, int numComp, vtkDataArray *outArray,
float nullValue)
{
RealArrayPair<T,float> *pair =
new RealArrayPair<T,float>(inData,outData,numPts,numComp,outArray,nullValue);
new RealArrayPair<T,float>(inData,outData,numTuples,numComp,
outArray,nullValue);
list->Arrays.push_back(pair);
}
......@@ -58,9 +62,10 @@ IsExcluded(vtkDataArray *da)
}
//----------------------------------------------------------------------------
// Add an array pair (input,output) using the name provided for the output.
// Add an array pair (input,output) using the name provided for the output. The
// numTuples is the number of output tuples allocated.
inline vtkDataArray* ArrayList::
AddArrayPair(vtkIdType numPts, vtkDataArray *inArray,
AddArrayPair(vtkIdType numTuples, vtkDataArray *inArray,
vtkStdString &outArrayName, double nullValue, bool promote)
{
if (this->IsExcluded(inArray))
......@@ -74,14 +79,14 @@ AddArrayPair(vtkIdType numPts, vtkDataArray *inArray,
{
outArray = vtkFloatArray::New();
outArray->SetNumberOfComponents(inArray->GetNumberOfComponents());
outArray->SetNumberOfTuples(inArray->GetNumberOfTuples());
outArray->SetNumberOfTuples(numTuples);
outArray->SetName(outArrayName);
void *iD = inArray->GetVoidPointer(0);
void *oD = outArray->GetVoidPointer(0);
switch (iType)
{
vtkTemplateMacro(CreateRealArrayPair(this, static_cast<VTK_TT *>(iD),
static_cast<float*>(oD),numPts,inArray->GetNumberOfComponents(),
static_cast<float*>(oD),numTuples,inArray->GetNumberOfComponents(),
outArray,static_cast<float>(nullValue)));
}//over all VTK types
}
......@@ -89,14 +94,14 @@ AddArrayPair(vtkIdType numPts, vtkDataArray *inArray,
{
outArray = inArray->NewInstance();
outArray->SetNumberOfComponents(inArray->GetNumberOfComponents());
outArray->SetNumberOfTuples(inArray->GetNumberOfTuples());
outArray->SetNumberOfTuples(numTuples);
outArray->SetName(outArrayName);
void *iD = inArray->GetVoidPointer(0);
void *oD = outArray->GetVoidPointer(0);
switch (iType)
{
vtkTemplateMacro(CreateArrayPair(this, static_cast<VTK_TT *>(iD),
static_cast<VTK_TT *>(oD),numPts,inArray->GetNumberOfComponents(),
static_cast<VTK_TT *>(oD),numTuples,inArray->GetNumberOfComponents(),
outArray,static_cast<VTK_TT>(nullValue)));
}//over all VTK types
}//promote integral types
......
set(Module_SRCS
vtkBooleanTexture.cxx
vtkShepardMethod.cxx
vtkVoxelModeller.cxx
vtkSurfaceReconstructionFilter.cxx
vtkCheckerboardSplatter.cxx
vtkFastSplatter.cxx
vtkGaussianSplatter.cxx
vtkCheckerboardSplatter.cxx
vtkSampleFunction.cxx
vtkPointLoad.cxx
vtkImageCursor3D.cxx
vtkImageRectilinearWipe.cxx
vtkImageToPoints.cxx
vtkTriangularTexture.cxx
vtkPointLoad.cxx
vtkSampleFunction.cxx
vtkShepardMethod.cxx
vtkSliceCubes.cxx
vtkSurfaceReconstructionFilter.cxx
vtkTriangularTexture.cxx
vtkVoxelModeller.cxx
)
vtk_module_library(${vtk-module} ${Module_SRCS})
......@@ -31,6 +31,7 @@ vtkStandardNewMacro(vtkRendererSource);
vtkCxxSetObjectMacro(vtkRendererSource,Input,vtkRenderer);
//----------------------------------------------------------------------------
vtkRendererSource::vtkRendererSource()
{
this->Input = NULL;
......@@ -38,12 +39,13 @@ vtkRendererSource::vtkRendererSource()
this->RenderFlag = 0;
this->DepthValues = 0;
this->DepthValuesInScalars = 0;
this->DepthValuesOnly = 0;
this->SetNumberOfInputPorts(0);
this->SetNumberOfOutputPorts(1);
}
//----------------------------------------------------------------------------
vtkRendererSource::~vtkRendererSource()
{
if (this->Input)
......@@ -53,13 +55,13 @@ vtkRendererSource::~vtkRendererSource()
}
}
//----------------------------------------------------------------------------
void vtkRendererSource::RequestData(vtkInformation*,
vtkInformationVector**,
vtkInformationVector* outputVector)
{
int numOutPts;
vtkIdType numOutPts;
float x1,y1,x2,y2;
unsigned char *pixels, *ptr;
int dims[3];
vtkInformation* info = outputVector->GetInformationObject(0);
......@@ -69,76 +71,91 @@ void vtkRendererSource::RequestData(vtkInformation*,
info->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), uExtent);
output->SetExtent(uExtent);
output->AllocateScalars(info);
vtkUnsignedCharArray *outScalars =
vtkArrayDownCast<vtkUnsignedCharArray>(output->GetPointData()->GetScalars());
vtkDebugMacro(<<"Extracting image");
// Make sure there is proper input
if (this->Input == NULL)
{
return;
}
if (this->DepthValuesInScalars)
{
outScalars->SetName("RGBValues");
}
else
{
outScalars->SetName("RGBZValues");
}
vtkRenderWindow *renWin;
vtkDebugMacro(<<"Converting points");
if (this->Input == NULL )
{
vtkErrorMacro(<<"Please specify a renderer as input!");
return;
}
renWin = this->Input->GetRenderWindow();
vtkRenderWindow *renWin = this->Input->GetRenderWindow();
if (renWin == NULL)
{
vtkErrorMacro(<<"Renderer needs to be associated with renderin window!");
return;
}
// We're okay to go. There are two paths to proceed. Simply a depth image,
// or some combination of depth image and color scalars.
// calc the pixel range for the renderer
if (this->RenderFlag)
{
renWin->Render();
}
// calc the pixel range for the renderer
x1 = this->Input->GetViewport()[0]*
((this->Input->GetRenderWindow())->GetSize()[0] - 1);
y1 = this->Input->GetViewport()[1]*
((this->Input->GetRenderWindow())->GetSize()[1] - 1);
x2 = this->Input->GetViewport()[2]*
((this->Input->GetRenderWindow())->GetSize()[0] - 1);
y2 = this->Input->GetViewport()[3]*
((this->Input->GetRenderWindow())->GetSize()[1] - 1);
x1 = this->Input->GetViewport()[0]*(renWin->GetSize()[0] - 1);
y1 = this->Input->GetViewport()[1]*(renWin->GetSize()[1] - 1);
x2 = this->Input->GetViewport()[2]*(renWin->GetSize()[0] - 1);
y2 = this->Input->GetViewport()[3]*(renWin->GetSize()[1] - 1);
if (this->WholeWindow)
{
x1 = 0;
y1 = 0;
x2 = (this->Input->GetRenderWindow())->GetSize()[0] - 1;
y2 = (this->Input->GetRenderWindow())->GetSize()[1] - 1;
x2 = renWin->GetSize()[0] - 1;
y2 = renWin->GetSize()[1] - 1;
}
// Get origin, aspect ratio and dimensions from this->Input
// Get origin, aspect ratio and dimensions from the input
dims[0] = static_cast<int>(x2 - x1 + 1);
dims[1] = static_cast<int>(y2 -y1 + 1);
dims[2] = 1;
output->SetDimensions(dims);
// Allocate data. Scalar type is FloatScalars.
numOutPts = dims[0] * dims[1];
pixels = (this->Input->GetRenderWindow())->GetPixelData(static_cast<int>(x1),
static_cast<int>(y1),
static_cast<int>(x2),
static_cast<int>(y2)
,1);
// If simply requesting depth values (no colors), do the following
// and then return.
if ( this->DepthValuesOnly )
{
float *zBuf, *ptr;
output->AllocateScalars(info);
vtkFloatArray *outScalars =
vtkArrayDownCast<vtkFloatArray>(output->GetPointData()->GetScalars());
outScalars->SetName("ZValues");
ptr = outScalars->WritePointer(0, numOutPts);
zBuf = renWin->GetZbufferData(
static_cast<int>(x1),static_cast<int>(y1),static_cast<int>(x2),
static_cast<int>(y2));
memcpy(ptr, zBuf, numOutPts*sizeof(float));
delete [] zBuf;
return;
}
// Okay requesting color scalars plus possibly depth values.
unsigned char *pixels, *ptr;
output->AllocateScalars(info);
vtkUnsignedCharArray *outScalars =
vtkArrayDownCast<vtkUnsignedCharArray>(output->GetPointData()->GetScalars());
if (this->DepthValuesInScalars)
{
outScalars->SetName("RGBValues");
}
else
{
outScalars->SetName("RGBZValues");
}
// Allocate data. Scalar type is FloatScalars.
pixels = renWin->GetPixelData(static_cast<int>(x1),
static_cast<int>(y1),
static_cast<int>(x2),
static_cast<int>(y2), 1);
// allocate scalars
int nb_comp = output->GetNumberOfScalarComponents();
......@@ -153,7 +170,7 @@ void vtkRendererSource::RequestData(vtkInformation*,
// Lets get the ZBuffer also, if requested.
if (this->DepthValues || this->DepthValuesInScalars)
{
float *zBuf = (this->Input->GetRenderWindow())->GetZbufferData(
float *zBuf = renWin->GetZbufferData(
static_cast<int>(x1),static_cast<int>(y1),static_cast<int>(x2),
static_cast<int>(y2));
......@@ -200,6 +217,7 @@ void vtkRendererSource::RequestData(vtkInformation*,
delete [] pixels;
}
//----------------------------------------------------------------------------
void vtkRendererSource::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os,indent);
......@@ -219,9 +237,11 @@ void vtkRendererSource::PrintSelf(ostream& os, vtkIndent indent)
os << indent << "Whole Window: " << (this->WholeWindow ? "On\n" : "Off\n");
os << indent << "Depth Values: " << (this->DepthValues ? "On\n" : "Off\n");
os << indent << "Depth Values In Scalars: " << (this->DepthValuesInScalars ? "On\n" : "Off\n");
os << indent << "Depth Values Only: " << (this->DepthValuesOnly ? "On\n" : "Off\n");
}
//----------------------------------------------------------------------------
unsigned long vtkRendererSource::GetMTime()
{
vtkRenderer *ren = this->GetInput();
......@@ -294,7 +314,7 @@ void vtkRendererSource::RequestInformation (
if (ren == NULL || ren->GetRenderWindow() == NULL)
{
vtkErrorMacro("The input renderer has not been set yet!!!");
return;
return;
}
// calc the pixel range for the renderer
......@@ -319,8 +339,15 @@ void vtkRendererSource::RequestInformation (
outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), extent, 6);
vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_UNSIGNED_CHAR,
3 + (this->DepthValuesInScalars ? 1:0));
if ( this->DepthValuesOnly )
{
vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_FLOAT, 1);
}
else
{
vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_UNSIGNED_CHAR,
3 + (this->DepthValuesInScalars ? 1:0));
}
}
//----------------------------------------------------------------------------
......@@ -351,6 +378,7 @@ vtkImageData* vtkRendererSource::GetOutput()
return vtkImageData::SafeDownCast(this->GetOutputDataObject(0));
}
//----------------------------------------------------------------------------
int vtkRendererSource::FillOutputPortInformation(
int vtkNotUsed(port), vtkInformation* info)
{
......
......@@ -12,21 +12,34 @@
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
// .NAME vtkRendererSource - take a renderer into the pipeline
// .NAME vtkRendererSource - take a renderer's image and/or depth map into the pipeline
// .SECTION Description
// vtkRendererSource is a source object that gets its input from a
// renderer and converts it to structured points. This can then be
// used in a visualization pipeline. You must explicitly send a
// Modify() to this object to get it to reload its data from the
// renderer. Consider using vtkWindowToImageFilter instead of this
// vtkRendererSource is a source object whose input is a renderer's image
// and/or depth map, which is then used to produce an output image. This
// output can then be used in the visualization pipeline. You must explicitly
// send a Modify() to this object to get it to reload its data from the
// renderer. Consider also using vtkWindowToImageFilter instead of this
// class.
//
// The data placed into the output is the renderer's image rgb values.
// Optionally, you can also grab the image depth (e.g., z-buffer) values, and
// place then into the output (point) field data.
// .SECTION see also
// vtkWindowToImageFilter vtkRenderer vtkStructuredPoints
// By default, the data placed into the output is the renderer's image RGB
// values (these color scalars are represented by unsigned chars, one per
// color channel). Optionally, you can also grab the image depth (e.g.,
// z-buffer) values, and include it in the output in one of three ways. 1)
// First, when the data member DepthValues is enabled, a separate float array
// of these depth values is included in the output point data with array name
// "ZBuffer". 2) If DepthValuesInScalars is enabled, then the z-buffer values
// are shifted and scaled to fit into an unsigned char and included in the
// output image (so the output image pixels are four components RGBZ). Note
// that DepthValues and and DepthValuesInScalars can be enabled
// simultaneously if desired. Finally 3) if DepthValuesOnly is enabled, then
// the output image consists only of the z-buffer values represented by a
// single component float array; and the data members DepthValues and
// DepthValuesInScalars are ignored.
// .SECTION See Also
// vtkWindowToImageFilter vtkRendererPointCloudSource vtkRenderer
// vtkImageData vtkDepthImageToPointCloud
#ifndef vtkRendererSource_h
#define vtkRendererSource_h
......@@ -64,7 +77,7 @@ public:
vtkBooleanMacro(WholeWindow, int);
// Description:
// If this flag is on, the Executing causes a render first.
// If this flag is on, then filter execution causes a render first.
vtkSetMacro(RenderFlag, int);
vtkGetMacro(RenderFlag, int);
vtkBooleanMacro(RenderFlag, int);
......@@ -86,6 +99,17 @@ public:
vtkGetMacro(DepthValuesInScalars, int);
vtkBooleanMacro(DepthValuesInScalars, int);
// Description:
// A boolean value to control whether to grab only the z-buffer (i.e.,
// depth values) without the associated image (color scalars) data. If
// enabled, the output data contains only a depth image which is the
// z-buffer values represented by float values. By default, this is
// disabled. Note that if enabled, then the DepthValues and
// DepthValuesInScalars are ignored.
vtkSetMacro(DepthValuesOnly, int);
vtkGetMacro(DepthValuesOnly, int);
vtkBooleanMacro(DepthValuesOnly, int);
// Description:
// Get the output data object for a port on this algorithm.
vtkImageData* GetOutput();
......@@ -112,6 +136,7 @@ protected:
int RenderFlag;
int DepthValues;
int DepthValuesInScalars;
int DepthValuesOnly;
// see algorithm for more info
virtual int FillOutputPortInformation(int port, vtkInformation* info);
......
......@@ -45,8 +45,9 @@
// VTK 4.4+, machine-independent behavior is not automatically
// assured because of these dependencies.
// .SECTION see also
// vtkWindow vtkRenderLargeImage
// .SECTION See Also
// vtkRendererSource vtkRendererPointCloudSource vtkWindow
// vtkRenderLargeImage
#ifndef vtkWindowToImageFilter_h
#define vtkWindowToImageFilter_h
......
set(Module_SRCS
vtkDepthImageToPointCloud.cxx
vtkImageResliceMapper.cxx
vtkImageSliceCollection.cxx
vtkImageStack.cxx
......
vtk_add_test_python(
TestDepthImageToPointCloud.py
)
if ("${VTK_RENDERING_BACKEND}" STREQUAL "OpenGL2")
vtk_add_test_python(
TestDepthImageToPointCloud-TwoInputs.py
)
endif()
#!/usr/bin/env python
import vtk
from vtk.test import Testing
from vtk.util.misc import vtkGetDataRoot
VTK_DATA_ROOT = vtkGetDataRoot()
# Parameters for testing
sze = 300
# Graphics stuff
ren0 = vtk.vtkRenderer()
ren0.SetViewport(0,0,0.5,1)
ren1 = vtk.vtkRenderer()
ren1.SetViewport(0.5,0,1,1)
renWin = vtk.vtkRenderWindow()
renWin.SetSize(2*sze+100,sze)
renWin.AddRenderer(ren0)
renWin.AddRenderer(ren1)
iren = vtk.vtkRenderWindowInteractor()
iren.SetRenderWindow(renWin)
# Create pipeline, render simple object. We'll also color
# the sphere to generate color scalars.
sphere = vtk.vtkSphereSource()
sphere.SetCenter(0,0,0)
sphere.SetRadius(1)
ele = vtk.vtkElevationFilter()
ele.SetInputConnection(sphere.GetOutputPort())
ele.SetLowPoint(0,-1,0)
ele.SetHighPoint(0,1,0)
sphereMapper = vtk.vtkPolyDataMapper()
sphereMapper.SetInputConnection(ele.GetOutputPort())
sphereActor = vtk.vtkActor()
sphereActor.SetMapper(sphereMapper)
ren0.AddActor(sphereActor)
ren0.SetBackground(0,0,0)
iren.Initialize()
ren0.ResetCamera()
ren0.GetActiveCamera().SetClippingRange(6,9)
renWin.Render()
# Extract rendered geometry, convert to point cloud
# Grab just z-values
renSource = vtk.vtkRendererSource()
renSource.SetInput(ren0)
renSource.WholeWindowOff()
renSource.DepthValuesOnlyOn()
renSource.Update()
# Grab color values
renSource1 = vtk.vtkRendererSource()
renSource1.SetInput(ren0)
renSource1.WholeWindowOff()
renSource1.DepthValuesOff()
renSource1.DepthValuesInScalarsOff()
renSource1.Update()
# Note that the vtkPointGaussianMapper does not require vertex cells
pc = vtk.vtkDepthImageToPointCloud()
pc.SetInputConnection(0,renSource.GetOutputPort())
pc.SetInputConnection(1,renSource1.GetOutputPort())
pc.SetCamera(ren0.GetActiveCamera())
pc.CullNearPointsOn()
pc.CullFarPointsOn()
pc.ProduceVertexCellArrayOff()
print(pc)
timer = vtk.vtkTimerLog()
timer.StartTimer()
pc.Update()
timer.StopTimer()
time = timer.GetElapsedTime()
print("Generate point cloud: {0}".format(time))
pcMapper = vtk.vtkPointGaussianMapper()
pcMapper.SetInputConnection(pc.GetOutputPort())
pcMapper.EmissiveOff()
pcMapper.SetScaleFactor(0.0)
pcActor = vtk.vtkActor()
pcActor.SetMapper(pcMapper)
ren1.AddActor(pcActor)
ren1.SetBackground(0,0,0)
cam = ren1.GetActiveCamera()
cam.SetFocalPoint(0,0,0)
cam.SetPosition(1,1,1)
ren1.ResetCamera()
renWin.Render()
#iren.Start()
#!/usr/bin/env python
import vtk
from vtk.test import Testing
from vtk.util.misc import vtkGetDataRoot
VTK_DATA_ROOT = vtkGetDataRoot()
# Parameters for testing
sze = 300
# Graphics stuff
ren0 = vtk.vtkRenderer()
ren0.SetViewport(0,0,0.5,1)
ren1 = vtk.vtkRenderer()
ren1.SetViewport(0.5,0,1,1)
renWin = vtk.vtkRenderWindow()
renWin.SetSize(2*sze+100,sze)
#renWin.SetSize(2*sze,sze)
renWin.AddRenderer(ren0)
renWin.AddRenderer(ren1)
iren = vtk.vtkRenderWindowInteractor()
iren.SetRenderWindow(renWin)
# Create pipeline, render simple object. We'll also color
# the plane.
plane = vtk.vtkPlaneSource()
plane.SetOrigin(0,0,0)
plane.SetPoint1(2,0,0)
plane.SetPoint2(0,1,0)
ele = vtk.vtkElevationFilter()
ele.SetInputConnection(plane.GetOutputPort())
ele.SetLowPoint(0,0,0)
ele.SetHighPoint(0,1,0)
planeMapper = vtk.vtkPolyDataMapper()
planeMapper.SetInputConnection(ele.GetOutputPort())
planeActor = vtk.vtkActor()
planeActor.SetMapper(planeMapper)
ren0.AddActor(planeActor)
ren0.SetBackground(1,1,1)
iren.Initialize()
renWin.Render()
# Extract rendered geometry, convert to point cloud
renSource = vtk.vtkRendererSource()
renSource.SetInput(ren0)
renSource.WholeWindowOff()
renSource.DepthValuesOn()
renSource.Update()
pc = vtk.vtkDepthImageToPointCloud()
pc.SetInputConnection(renSource.GetOutputPort())
pc.SetCamera(ren0.GetActiveCamera())
pc.CullFarPointsOff()
timer = vtk.vtkTimerLog()
timer.StartTimer()
pc.Update()
timer.StopTimer()
time = timer.GetElapsedTime()
print("Generate point cloud: {0}".format(time))
pcMapper = vtk.vtkPolyDataMapper()
pcMapper.SetInputConnection(pc.GetOutputPort())
pcActor = vtk.vtkActor()
pcActor.SetMapper(pcMapper)
ren1.AddActor(pcActor)
ren1.SetBackground(0,0,0)
cam = ren1.GetActiveCamera()
cam.SetFocalPoint(0,0,0)
cam.SetPosition(1,1,1)
ren1.ResetCamera()
renWin.Render()
#iren.Start()
/*=========================================================================
Program: Visualization Toolkit
Module: vtkDepthImageToPointCloud.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.
=========================================================================*/
#include "vtkDepthImageToPointCloud.h"
#include "vtkCommand.h"
#include "vtkFloatArray.h"
#include "vtkCellArray.h"
#include "vtkPolyData.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"
#include "vtkImageData.h"
#include "vtkPointData.h"
#include "vtkCamera.h"
#include "vtkMatrix4x4.h"
#include "vtkRenderWindow.h"
#include "vtkRenderer.h"
#include "vtkCoordinate.h"
#include "vtkStreamingDemandDrivenPipeline.h"
#include "vtkSMPTools.h"
#include "vtkArrayListTemplate.h" // For processing attribute data
vtkStandardNewMacro(vtkDepthImageToPointCloud);
vtkCxxSetObjectMacro(vtkDepthImageToPointCloud,Camera,vtkCamera);
//----------------------------------------------------------------------------
// Helper classes to support efficient computing, and threaded execution.
namespace {
// Map input point id to output point id. This map is needed because of the
// optionally capability to cull near and far points.
template <typename T>
void MapPoints(vtkIdType numPts, T *depths, bool cullNear, bool cullFar,
vtkIdType *map, vtkIdType &numOutPts)
{
numOutPts = 0;
float d;
for (vtkIdType ptId=0; ptId < numPts; ++depths, ++map, ++ptId)
{
d = static_cast<float>(*depths);
if ( (cullNear && d <= 0.0) || (cullFar && d >= 1.0) )
{
*map = (-1);
}
else
{
*map = numOutPts++;
}
}
}
// This class performs point by point transformation. The view matrix is
// used to transform each pixel. IMPORTANT NOTE: The transformation occurs
// by normalizing the image pixels into the (-1,1) view space (depth values
// are passed thru). The process follows the vtkCoordinate class which is
// the standard for VTK rendering transformations. Subtle differences in
<