MultipleLayersAndWindows
Repository source: MultipleLayersAndWindows
Description¶
Demonstrates the use of four renderers in two layers. The left renderers camera is independent of the right renderers camera.
There are four objects in two windows and two layers.
Layers | Left | Right |
---|---|---|
0 | cube | cone |
1 | sphere | cylinder |
When the program first runs, the top-most layer will be the active layer, (layer 1 in this case). Objects in layer 0 will be almost transparent.
- Pressing 0 on the keyboard will let you manipulate the objects in layer 0. Objects in layer 1 will be almost transparent.
- Pressing 1 on the keyboard will let you manipulate the objects in layer 1. Objects in layer 0 will be almost transparent.
Note:
- The layer 0 background is the only visible background; backgrounds in layer 1 and subsequent layers are transparent.
- It is easy to access the renderers and actors from the interactor by iterating through the renderer and actor collections.
- In renderer collections and actor collections it is important to remember that the references are stored in last in - first out order.
Info
Also see the LayeredActors and TransparentBackground examples.
Other languages
See (PythonicAPI)
Question
If you have a question about this example, please use the VTK Discourse Forum
Code¶
MultipleLayersAndWindows.cxx
#include <vtkActor.h>
#include <vtkCallbackCommand.h>
#include <vtkConeSource.h>
#include <vtkCubeSource.h>
#include <vtkCylinderSource.h>
#include <vtkInteractorObserver.h>
#include <vtkInteractorStyleTrackballCamera.h>
#include <vtkNamedColors.h>
#include <vtkNew.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkRendererCollection.h>
#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>
#include <array>
#include <iostream>
#include <vector>
namespace {
/**
* Select the layer to manipulate.
*/
void SelectLayer(vtkObject* caller, long unsigned int eventId, void* clientData,
void* callData);
} // namespace
int main(int, char*[])
{
vtkNew<vtkNamedColors> colors;
// Set the background color.
std::array<unsigned char, 4> cubeColor{{250, 128, 114, 255}};
colors->SetColor("CubeColor", cubeColor.data());
std::array<unsigned char, 4> bkg{{230, 230, 230, 255}};
colors->SetColor("BkgColor", bkg.data());
// Create the rendering windows and renderers.
std::array<vtkSmartPointer<vtkRenderer>, 2> leftRends;
std::array<vtkSmartPointer<vtkRenderer>, 2> rightRends;
vtkNew<vtkRenderWindow> renWin;
renWin->SetSize(1200, 600);
renWin->SetPosition(0, 50);
renWin->SetWindowName("MultipleLayersAndWindows");
renWin->SetNumberOfLayers(2);
// Define the renderers setting viewport, layer and color.
for (int i = 0; i < 2; ++i)
{
leftRends[i] = vtkSmartPointer<vtkRenderer>::New();
leftRends[i]->SetViewport(0, 0, 0.5, 1);
leftRends[i]->SetBackground(colors->GetColor3d("BkgColor").GetData());
leftRends[i]->SetLayer(i);
renWin->AddRenderer(leftRends[i]);
rightRends[i] = vtkSmartPointer<vtkRenderer>::New();
rightRends[i]->SetViewport(0.5, 0, 1, 1);
rightRends[i]->SetBackground(colors->GetColor3d("Linen").GetData());
rightRends[i]->SetLayer(i);
renWin->AddRenderer(rightRends[i]);
}
vtkNew<vtkRenderWindowInteractor> iRen;
iRen->SetRenderWindow(renWin);
vtkNew<vtkInteractorStyleTrackballCamera> style;
iRen->SetInteractorStyle(style);
// Create an actor and give it conical geometry.
vtkNew<vtkConeSource> cone;
cone->SetResolution(8);
vtkNew<vtkPolyDataMapper> coneMapper;
coneMapper->SetInputConnection(cone->GetOutputPort());
vtkNew<vtkActor> coneActor;
coneActor->SetMapper(coneMapper);
coneActor->GetProperty()->SetColor(colors->GetColor3d("CubeColor").GetData());
// Create an actor and give it cylindrical geometry.
vtkNew<vtkCylinderSource> cylinder;
cylinder->SetResolution(8);
cylinder->SetHeight(0.5);
cylinder->SetRadius(0.25);
vtkNew<vtkPolyDataMapper> cylinderMapper;
cylinderMapper->SetInputConnection(cylinder->GetOutputPort());
vtkNew<vtkActor> cylinderActor;
cylinderActor->SetMapper(cylinderMapper);
cylinderActor->GetProperty()->SetColor(
colors->GetColor3d("Peacock").GetData());
// Create an actor and give it cubic geometry.
vtkNew<vtkCubeSource> cube;
vtkNew<vtkPolyDataMapper> cubeMapper;
cubeMapper->SetInputConnection(cube->GetOutputPort());
vtkNew<vtkActor> cubeActor;
cubeActor->SetMapper(cubeMapper);
cubeActor->GetProperty()->SetColor(colors->GetColor3d("CubeColor").GetData());
// Create an actor and give it spherical geometry.
vtkNew<vtkSphereSource> sphere;
sphere->SetRadius(0.25);
vtkNew<vtkPolyDataMapper> sphereMapper;
sphereMapper->SetInputConnection(sphere->GetOutputPort());
vtkNew<vtkActor> sphereActor;
sphereActor->SetMapper(sphereMapper);
sphereActor->GetProperty()->SetColor(colors->GetColor3d("Peacock").GetData());
// Assign our actors to the renderers.
leftRends[0]->AddActor(cubeActor); // Cube -> Left renderer, Layer 0
leftRends[1]->AddActor(sphereActor); // Sphere -> Left renderer, Layer 1
rightRends[0]->AddActor(coneActor); // Cone -> Right renderer, Layer 0
rightRends[1]->AddActor(cylinderActor); // Cylinder -> Right renderer, Layer 1
// Hide the layer 0 actors.
cubeActor->GetProperty()->SetOpacity(0.1);
coneActor->GetProperty()->SetOpacity(0.1);
vtkNew<vtkCallbackCommand> keypressCallback;
keypressCallback->SetCallback(SelectLayer);
iRen->AddObserver(vtkCommand::KeyPressEvent, keypressCallback);
// Draw the resulting scene.
renWin->Render();
// Set the active cameras.
leftRends[1]->SetActiveCamera(leftRends[0]->GetActiveCamera());
rightRends[1]->SetActiveCamera(rightRends[0]->GetActiveCamera());
iRen->Start();
return EXIT_SUCCESS;
}
namespace {
void SelectLayer(vtkObject* caller, long unsigned int vtkNotUsed(eventId),
void* vtkNotUsed(clientData), void* vtkNotUsed(callData))
{
vtkRenderWindowInteractor* iRen =
static_cast<vtkRenderWindowInteractor*>(caller);
vtkRendererCollection* renderers = iRen->GetRenderWindow()->GetRenderers();
auto numberOfItems = renderers->GetNumberOfItems();
if (numberOfItems < 4)
{
std::cerr << "We need at least four renderers, we have only "
<< renderers->GetNumberOfItems() << std::endl;
return;
}
std::vector<vtkRenderer*> rens;
renderers->InitTraversal();
// Top item is rens[0] and the bottom item is rens[numberOfItems-1].
for (auto i = 0; i < numberOfItems; ++i)
{
rens.push_back(renderers->GetNextItem());
}
// Reverse so that the bottom item is rens[0]
// and the top item is rens[numberOfItems-1].
std::reverse(rens.begin(), rens.end());
/**
* Set the actor properties.
*
* Note: rens is the list of renderers defined in the caller.
*
* @param idx Index of the specified renderer.
* @param opacity Opacity of the first actor in the specified renderer.
*
*/
auto SetActorProperties = [&](const int& idx, const double& opacity) {
auto actor = rens[idx]->GetActors();
actor->InitTraversal();
actor->GetNextActor()->GetProperty()->SetOpacity(opacity);
};
std::string key = iRen->GetKeySym();
if (key == "0" || key == "KP_0")
{
SetActorProperties(0, 0.1);
SetActorProperties(1, 0.1);
SetActorProperties(2, 1);
SetActorProperties(3, 1);
std::cout << "Selected layer 0." << std::endl;
rens[0]->InteractiveOff(); // Cylinder -> Right renderer, Layer 1
rens[1]->InteractiveOff(); // Sphere -> Left renderer, Layer 1
rens[2]->InteractiveOn(); // Cone -> Right renderer, Layer 0
rens[3]->InteractiveOn(); // Cube -> Left renderer, Layer 0
}
if (key == "1" || key == "KP_1")
{
SetActorProperties(0, 1);
SetActorProperties(1, 1);
SetActorProperties(2, 0.1);
SetActorProperties(3, 0.1);
std::cout << "Selected layer 1." << std::endl;
rens[0]->InteractiveOn(); // Cylinder -> Right renderer, Layer 1
rens[1]->InteractiveOn(); // Sphere -> Left renderer, Layer 1
rens[2]->InteractiveOff(); // Cone -> Right renderer, Layer 0
rens[3]->InteractiveOff(); // Cube -> Left renderer, Layer 0
}
iRen->Render();
}
} // namespace
CMakeLists.txt¶
cmake_minimum_required(VERSION 3.12 FATAL_ERROR)
project(MultipleLayersAndWindows)
find_package(VTK COMPONENTS
CommonColor
CommonCore
FiltersSources
InteractionStyle
RenderingContextOpenGL2
RenderingCore
RenderingFreeType
RenderingGL2PSOpenGL2
RenderingOpenGL2
)
if (NOT VTK_FOUND)
message(FATAL_ERROR "MultipleLayersAndWindows: Unable to find the VTK build folder.")
endif()
# Prevent a "command line is too long" failure in Windows.
set(CMAKE_NINJA_FORCE_RESPONSE_FILE "ON" CACHE BOOL "Force Ninja to use response files.")
add_executable(MultipleLayersAndWindows MACOSX_BUNDLE MultipleLayersAndWindows.cxx )
target_link_libraries(MultipleLayersAndWindows PRIVATE ${VTK_LIBRARIES}
)
# vtk_module_autoinit is needed
vtk_module_autoinit(
TARGETS MultipleLayersAndWindows
MODULES ${VTK_LIBRARIES}
)
Download and Build MultipleLayersAndWindows¶
Click here to download MultipleLayersAndWindows and its CMakeLists.txt file. Once the tarball MultipleLayersAndWindows.tar has been downloaded and extracted,
cd MultipleLayersAndWindows/build
If VTK is installed:
cmake ..
If VTK is not installed but compiled on your system, you will need to specify the path to your VTK build:
cmake -DVTK_DIR:PATH=/home/me/vtk_build ..
Build the project:
make
and run it:
./MultipleLayersAndWindows
WINDOWS USERS
Be sure to add the VTK bin directory to your path. This will resolve the VTK dll's at run time.