RVTK Example: Data Representation (Mappers and Actors)


AbstractMapper
Mapper
Despite that datasets are first passed to mappers and later the mapper is sent to actor (as shown on pipeline diagramm), the selection of right mapper and actor is done in opposite direction. That means the type of dataset and the result you want to get defines the choice of actor and then, depending on the type of actor and the type of dataset, the mapper is selected.
The VTK's idea was that the actor (descendant of vtkProp class) incapsulates "physical" properties of the model (its color, opacity, roughness of its surface, its placement in the space) and the mapper (descendant of vtkAbstractMapper) define the methods to render 3D model on 2D plane. This division seems to me somethat arbitrary, because the mapper also influences the appearence of rendered objects.
There are a lot of actors and mappers in VTK (the small part of mappers available in VTK are shown on the picture above). The mapper also defines  which part of the data stored in dataset object will be rendered on the screen. For example rendering only geometry data is not enough - geometry of all vtkImageDFatas is almost the same and the valuable information is contained in associated PointsAttributes. The mappers among other things deside which part of associated data will be rendered and how it must be done. The result will be very differnet for various type of mappers. For example vtkPolyDataMapper and vtkPolyDataMapper2D both are designed for mapping vtkPolyData classes but the first render with OpenGL engine and the second just projects data on XY plane.
The data model is sent to Mapper with $SetInput(...) method. Although the method's name is the same for all mappers the type of input parameter can be different for various mappers. vtkPolyDataMapper insists on parameter being vtkPolyData not just vtkDataSet.
For our purposes selecting vtkPolyDataMapper is good enough:
vtkPolyDataMapper()->mapper
mapper$SetInput(model)

Data associated with the model can be displayed as color/opacity value or not be displayed at all. This is controlled by the mapper's methods ScalarVisibilityOn()/ScalarVisibilityOff(). In the later case coloring of the model depends on the values provided by the actor. In the former case we have to let know the mapper which data have to be displayed (cells' or points' one).
To map arbitrary data to colors lookup tables are used.  Theirs role is like the role of palette() in R-graphics, this is just an array of color values with an alpha component. The lookup procedure is a constant approximation.
We install lookup table with discrete colors returned by palette() function (for models with large number of vertices/faces it is more convinient to define tables providing ramp value and Hue/Saturation/Intensity range which results in smoothly varying colors):
lut <- vtkLookupTable()
Palette<-palette()
lut$SetNumberOfColors(length(Palette))
lut$Build()
for (i in 1:length(Palette)){
lut$SetTableValue(i-1, c(t(col2rgb(Palette[i])),1))
}
Next we should instruct the mapper to use this lookuptable, how to map data's values to colors and what kind  of associated data (cells' or points' which is default) is to be displayed.

mapper$SetLookupTable(lut)
mapper$SetScalarRange(0, 7)
mapper$SetScalarModeToUseCellData()

Scalar range is mapped to the upper/lower limits of color space. If SetScalarRange is omitted the whole dataset's range is mapped to the whole color range.
The selection of the actor is implicitely present in the selection of the mapper. VTK contains a large number of actors/props any of which is designed to work with specific range of mappers. Props are different from the actor because props can include other actors and setting the transformation for prop influence all actor the prop includes. Some of the actors does not require mapper (and consequently datasets) and is intended to be used as decoration of the scene. Here is some parts of vtkProp's inheritance tree:

vtkProp3D Inheritance
If we had volumetric data set we would select vtkVolume actor and one of the mappers suitable for displaying that type of datasets (for example 3D grid with scalar values at the nodes) - vtkVolumeRayCastMapper, vtkVolumeTextureMapper or hardware specific vtkVolumeProMapper (all descendants of vtkVolumeMapper). For displaying the surfaces we select vtkActor which is a superclass, that is a virtual class which will create one of its descendants depending on the system characteristics.

actor<-vtkActor()
actor$GetClassName()

GetClassName(...) returns the name of the VTK class. In this case it is:
 [1] "vtkOpenGLActor"

With the next line we just install already created mapper for the actor rendering:

actor$SetMapper(mapper)

The one of actor's function is to define the relative placement of geometrical objects. It of course can be done with modification of input datasets but it is not convenient to scale the data just to make actor fit into predefined bounds. Here we create another actor with the same mapper (that means - with the same input data) but squeezed and moved along z-axis.

actor2<-vtkActor()
actor2$SetScale_v1(c(1,1,0.5))
actor2$SePosition_v1(c(0,0,1))

"_v1" suffix is appended by RVTK to multicast methods. SetScale and SetPosition have two casts which get argument as either an array or three values. Next we set color and opacity of the actor different from default ones (these properties will be used as fallback when the mapper does not decorate the actor). Actor's properties are available through the call to its companion class vtkProperty:

actor2$GetProperty()->property
property$SetColor(0.8,0,0)
property$SetOpacity(0.8)

The last actor we will create is the simple annotation attached to the top of the first tetrahedra. This is an example of the actor which does not require the mapper for rendering (at least it does not require the mapper to be created explicitely):

vtkCaptionActor2D()->cap
cap$SetCaption("Test VTK")
cap$SetAttachmentPoint(p[1,])

The last move is to create scene and put the actors on it. The scene is represented by vtkRenderer class which in fact is just a viewport on steroids. As each scene it has lights, camera, curtain (background) and special effects. In most cases the code below is enough.

vtkRenderer()->ren
ren$SetBackground(0.1,0.2,0.3)
ren$AddActor(actor)
ren$AddActor(actor2)
ren$AddActor(cap)

vtkRenderer is a superclass too. On my Linux ren in reality has the classname vtkOpenGLRenderer.
<Prev         Next>