I am working on a project that we need to render a huge number of instances of a source (for instance spheres, cones, planes and arrows), similitar to a point cloud.
Please, see below a image for purpose of demonstration of how the system works. On a real scenario, much more objects should be rendered.
The user is allowed to change the color and scale, hide those structures trough out a external interface.
Most importantly, the user will be able to insert and remove new intances.
I am wondering what is the best approach for this system in terms of performance. For instance, in the case of insertion and remotion of new structures we are looking for an approach that do not need to recompute all the previous instances as a new one is inserted or removed.
Should we use vtkGlyph3D, vtkGlyph3DMapper, vtkCompositePolydataMapper2? Is there a better approch for this type of application?
I know it’s been a long time, but for the benefit of others, I can tell you you don’t want to use vtkGlyph3D as I believe it makes copies of the data. I think you want to use vtkGlyph3DMapper with the source as a MultiBlockDataSet containing the polydatas of all of the possible glyph shapes. Input Data to this mapper should be the array of points where the glyphs belong, along with associated arrays that specify the index of the data in the dataset for each point, and probably an array for orientation as well.
something like this:
auto pointPD = vtkSmartPointer<vtkPolyData>::New();
auto points = vtkSmartPointer<vtkPoints>::New();
vtkNew<vtkFloatArray> orientations;
orientations->SetNumberOfComponents(3);
orientations->SetName("Orientations");
vtkNew<vtkIntArray> sourceIndices;
sourceIndices->SetNumberOfComponents(1);
sourceIndices->SetName("SourceIndices");
int instCnt = 0;
auto dataSet = vtkSmartPointer<vtkMultiPieceDataSet>::New();
dataSet->SetNumberOfPieces(previewParts.size());
for (auto &[source, trs] : parts) {
for (auto tr : trs) {
points->InsertNextPoint(pTr.matrix()(0, 3), pTr.matrix()(1, 3), pTr.matrix()(2, 3));
auto orientTr = vtkSmartPointer<vtkTransform>::New();
orientTr->GetMatrix()->DeepCopy(pTr.data());
auto o = orientTr->GetOrientation();
orientations->InsertNextTuple3(o[0], o[1], o[2]);
sourceIndices->InsertNextValue(instCnt);
}
auto polyData = source->getPolyData();
dataSet->SetPiece(instCnt++, polyData);
}
_glyphMapper->SetUseSourceTableTree(true);
_glyphMapper->SetSourceTableTree(dataSet);
pointPD->SetPoints(points);
pointPD->GetPointData()->AddArray(orientations);
pointPD->GetPointData()->AddArray(sourceIndices);
glyphMapper->SetInputData(pointPD);
glyphMapper->SetOrientationArray("Orientations");
glyphMapper->SetSourceIndexArray("SourceIndices");
glyphMapper->SetOrientationModeToRotation();
glyphMapper->SetOrient(true);
glyphMapper->SetSourceIndexing(true);
now if only I could figure out how to turn individual instances visibility on and off…
Thanks for the update. I would just note that both vtkGlyph3DMapper and vtkGlyph3D have their own advantages and disadvantages.
vtkGlyph3DMapper offloads work to the GPU, so it is preferable if you have GPU hardware and all you need to do is rendering of glyphs with some basic scaling/orienting/coloring options.
vtkGlyph3D provides vtkPolyData output, which can be saved into file or further processed or combined with other polydata. It also has more options for using various scalars for scaling/orienting/coloring the glyphs. It may be faster than vtkGlyph3DMapper if you use a software renderer, and it can handle extremely large meshes that would not fit into GPU memory.
Thank you Andras. Good points that Glyph3D has valid uses but visualizing large numbers of instances is probably not one of them correct?
We are trying to boost performance using glyphs as the complexity of what our users are doing increases. Glyphs are helping but it is a challenge to maintain performance. There are a lot of tradeoffs and gotchas. For example enabling picking slows things down as the shader program gets rebuilt between the pick/nonpick renders. For now we are ok turning off picking. I can provide a test case if you’d like to see but I think it’s pretty easy to produce. Just have a scenepicker and glyphs and it will happen
I would say that vtkGlyph3DMapper is a specialized tool that is much more limited but can be faster than vtkGlyph3D.
Picking is a very complex and expensive operation. However, if you don’t perform picking during camera rotation and you store the picking rendering result and reuse it until the scene is changed then the delay might not be noticeable.