Adding all vtkPoints at once

Hi,

I have a set of vtkPoints that keeps changing and I wish to refresh the screen with the new data
as fast as possible. My problem is it seems like the data has to be in a vtkCell to be displayable.

Adding points using:

v = vtkSmartPointer::New();
for(MIL_INT j = 0; j < nbPoints; j++)
{
v->InsertNextCell(3, VtkVerts[j]);
}

Is very slow and using something like vtkPolyVertex also does a for loop on all the points internally.

I am looking for something even more lightweigh where I could do something like:

SetData(*vtkPoints)
OR
SetVoidPointer(pointData)

and that data would be sent to the renderer immediately without having to set all points i
ndividually prior.

The only other option I have right now would be to parallelize the process which seems a bit overkill to me

Thank you for your help,
Jonathan Jackson

A common way of displaying points in VTK is with vtkGlyph3DMapper. No cells are required. The vtkGlyphMapper will use the GPU to display each point as whatever kind of shape you want.

It is possible to do in-place modifications to the vtkPoints, i.e. you can call points->SetPoint(i, x, y, z) to change a point and points->Resize(n) to resize the points array. Just make sure you call points->Modified() when you are done with all the changes, otherwise the VTK pipeline may not update when you render.

You don’t need to change the vert’s. Just change the points in the
polydata. The verts point to them with an index.

The vtkPoints are stored in a vtkFloatArray or vtkDoubleArray.

Also, yes, it is possible for vtkPoints to reference a block of memory that already contains the point triplets. You can also create a vtkFloatArray or vtkDoubleArray, link the array to your own data with array->SetArray(), and then link vtkPoints to the array with points->SetData(array).

E.g. something like this, where ‘data’ is a ‘float *’ to your block of point triplets:

array->SetArray(3, data, numpoints);
points->SetData(array);

Call points->Modified() whenever ‘data’ changes (and if the number of points changes, call array->SetArray() again).

However, using this initally :

p =            vtkSmartPointer<vtkPoints>::New();
polyData =     vtkSmartPointer<vtkPolyData>::New();
pdMapper =     vtkSmartPointer<vtkPolyDataMapper>::New();
vertexFilter = vtkSmartPointer<vtkVertexGlyphFilter>::New(); 
[...]
polyData->SetPoints(p);
vertexFilter->SetInputData(polyData);
vertexFilter->Update();
pdMapper->SetInputConnection(vertexFilter->GetOutputPort());
pdMapper->Update();
actor->SetMapper(pdMapper);

and then changing the points every time needed by doing :

SOAData->SetArray(0, PointCloud.GetPointerX(), SizeX, false, true);
SOAData->SetArray(1, PointCloud.GetPointerY(), SizeX, false, true);
SOAData->SetArray(2, PointCloud.GetPointerZ(), SizeX, false, true);
p->SetData(SOAData);
p->SetNumberOfPoints(SizeX);
p->Modified();
polyData->SetPoints(p);

Seems to defer some type of lengthy operation at render time. Which leads me
to believe something is done for everypoint (much like i’d be doing manually).
I feel like I just pushed the work I avoided by adding all the new verts to the render
phase. Render time is fourthfold longer when just modifying the points compared to
when adding them the first time.

You have the x, y, z components stored separately? I’m pretty sure that VTK will have to pack these so that the GPU can use them as a vertex buffer. Can your PointCloud store the points in packed format instead?

The components are stored separately, yes. But even when I interleave the values to have a packed buffer to pass its pointer to do:

  vtkDataArray* d = p->GetData();
  d->SetVoidArray(packedData, Size*3, 1);
  p->Modified();

The render time is as long as when I passed a SOA array. After tracing through the code it seems like
vtkOpenGLVertexBufferObject loses alot of time in

    array->GetRange(range, i);

Which mean I’ll have to trace enven deeper because I do not understand why the Range would have to be computed because I supplied it when I set the dataPointer using:

    d->SetVoidArray(packedData, Size*3, 1);

I’m not sure what you mean when you say you “supply the range”.

In any case, you should be able to work around this by instantiating your vtkPolyDataMapper as a vtkOpenGLPolyDataMapper and then calling

mapper->SetVBOShiftScaleMethod(vtkOpenGLVertexBufferObject::DISABLE_SHIFT_SCALE);

I was surprised to see that the mapper does this range computation by default. It’s very computationally expensive. Looks like it was a recent change to VTK (just a couple years old).

Thanks for the responsiveness!

This helped alot in both debug and release. I will probably be back when I feel like optimizing this even more. I feel like there may be more things we sould do with this to go even faster. Myabe as deep as the shaders that are used.

I now reach more or less 45fps while pushing 720k points each frame. Acceptable for now.

Thanks again David, you’re a good man!

Glad to hear that things worked out!

If you haven’t tried vtkGlyph3DMapper yet, it should (in theory) be able to give better performance than vtkVertexGlyphFilter + vtkPolyDataMapper but it might not have exactly the same options.

Unfortunately it doesn’t. It lenghtens the call to renWin->Render() tenfold. Even when I set the actor property SetRepresentationToPoints().

I was setting up my polyData as data to the 3dGlyphMapper and then setting it to the actor via SetMapper() and then updating the vtkPoints when they changed.

The vtkGlyph3DMapper most likely ignores SetRepresentationToPoints().

What ‘Source’ did you use with vtkGlyph3DMapper? To do the equivalent of what you are doing with vtkVertexGlyphFilter, the code would look something like this:

# generate a glyph polydata with 1 point and 1 vert cell
auto pointSource = vtkSmartPointer<vtkPointSource>::New();
pointSource->SetNumberOfPoints(1);
pointSource->SetRadius(0.0);
pointSource->Update();

auto mapper = vtkSmartPointer<vtkGlyph3DMapper>::New();
mapper->SetInputData(polyData);
mapper->SetSourceData(pointSource->GetOutput());

That gave me about the same result in render time as it did with the previous iteration.

auto pointSource = vtkSmartPointer<vtkPointSource>::New();
pointSource->SetNumberOfPoints(1);
pointSource->SetRadius(0.0);
pointSource->Update();

vtkDataArray* d = p->GetData();
d->SetVoidArray(packedData, Size * 3, 1);
p->Modified();
polyData->SetPoints(p);
auto mapper = vtkSmartPointer<vtkGlyph3DMapper>::New();
mapper->SetInputData(polyData);
mapper->SetSourceData(pointSource->GetOutput());

actor->SetMapper(mapperstrong text);

and then “p” is updated whenever my data changes by setting void arrays to it.

vtkDataArray* d = p->GetData();
d->SetVoidArray(packedData, Size * 3, 1);
p->Modified();

I am not sure what is the difference internally between this method and the previous metho but maybe this one creates a lot of VBOs that cant be treated as chunks of data when given to the shader.

J