RVTK Example: Data Representation (Mappers and Actors)
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:
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>