OpenVROrientedArrow
VTKExamples/Cxx/GeometricObjects/OpenVROrientedArrow
VTK + OpenVR OrientedArrow example.
Code¶
OpenVROrientedArrow.cxx
#include <vtkActor.h> #include <vtkArrowSource.h> #include <vtkMath.h> #include <vtkMinimalStandardRandomSequence.h> #include <vtkNamedColors.h> #include <vtkPolyData.h> #include <vtkPolyDataMapper.h> #include <vtkProperty.h> #include <vtkOpenVRRenderWindow.h> #include <vtkOpenVRRenderWindowInteractor.h> #include <vtkOpenVRRenderer.h> #include <vtkSmartPointer.h> #include <vtkSphereSource.h> #include <vtkTransform.h> #include <vtkTransformPolyDataFilter.h> #include <array> #define USER_MATRIX int main(int, char *[]) { vtkSmartPointer<vtkNamedColors> colors = vtkSmartPointer<vtkNamedColors>::New(); // Set the background color. std::array<unsigned char, 4> bkg{ { 26, 51, 77, 255 } }; colors->SetColor("BkgColor", bkg.data()); //Create an arrow. vtkSmartPointer<vtkArrowSource> arrowSource = vtkSmartPointer<vtkArrowSource>::New(); // Generate a random start and end point double startPoint[3]; double endPoint[3]; vtkSmartPointer<vtkMinimalStandardRandomSequence> rng = vtkSmartPointer<vtkMinimalStandardRandomSequence>::New(); rng->SetSeed(8775070); // For testing. for (auto i = 0; i < 3; ++i) { rng->Next(); startPoint[i] = rng->GetRangeValue(-10, 10); rng->Next(); endPoint[i] = rng->GetRangeValue(-10, 10); } // Compute a basis double normalizedX[3]; double normalizedY[3]; double normalizedZ[3]; // The X axis is a vector from start to end vtkMath::Subtract(endPoint, startPoint, normalizedX); double length = vtkMath::Norm(normalizedX); vtkMath::Normalize(normalizedX); // The Z axis is an arbitrary vector cross X double arbitrary[3]; for (auto i = 0; i < 3; ++i) { rng->Next(); arbitrary[i] = rng->GetRangeValue(-10, 10); } vtkMath::Cross(normalizedX, arbitrary, normalizedZ); vtkMath::Normalize(normalizedZ); // The Y axis is Z cross X vtkMath::Cross(normalizedZ, normalizedX, normalizedY); vtkSmartPointer<vtkMatrix4x4> matrix = vtkSmartPointer<vtkMatrix4x4>::New(); // Create the direction cosine matrix matrix->Identity(); for (auto i = 0; i < 3; i++) { matrix->SetElement(i, 0, normalizedX[i]); matrix->SetElement(i, 1, normalizedY[i]); matrix->SetElement(i, 2, normalizedZ[i]); } // Apply the transforms vtkSmartPointer<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New(); transform->Translate(startPoint); transform->Concatenate(matrix); transform->Scale(length, length, length); // Transform the polydata vtkSmartPointer<vtkTransformPolyDataFilter> transformPD = vtkSmartPointer<vtkTransformPolyDataFilter>::New(); transformPD->SetTransform(transform); transformPD->SetInputConnection(arrowSource->GetOutputPort()); //Create a mapper and actor for the arrow vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New(); vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New(); #ifdef USER_MATRIX mapper->SetInputConnection(arrowSource->GetOutputPort()); actor->SetUserMatrix(transform->GetMatrix()); #else mapper->SetInputConnection(transformPD->GetOutputPort()); #endif actor->SetMapper(mapper); actor->GetProperty()->SetColor(colors->GetColor3d("Cyan").GetData()); // Create spheres for start and end point vtkSmartPointer<vtkSphereSource> sphereStartSource = vtkSmartPointer<vtkSphereSource>::New(); sphereStartSource->SetCenter(startPoint); sphereStartSource->SetRadius(0.8); vtkSmartPointer<vtkPolyDataMapper> sphereStartMapper = vtkSmartPointer<vtkPolyDataMapper>::New(); sphereStartMapper->SetInputConnection(sphereStartSource->GetOutputPort()); vtkSmartPointer<vtkActor> sphereStart = vtkSmartPointer<vtkActor>::New(); sphereStart->SetMapper(sphereStartMapper); sphereStart->GetProperty()->SetColor(colors->GetColor3d("Yellow").GetData()); vtkSmartPointer<vtkSphereSource> sphereEndSource = vtkSmartPointer<vtkSphereSource>::New(); sphereEndSource->SetCenter(endPoint); sphereEndSource->SetRadius(0.8); vtkSmartPointer<vtkPolyDataMapper> sphereEndMapper = vtkSmartPointer<vtkPolyDataMapper>::New(); sphereEndMapper->SetInputConnection(sphereEndSource->GetOutputPort()); vtkSmartPointer<vtkActor> sphereEnd = vtkSmartPointer<vtkActor>::New(); sphereEnd->SetMapper(sphereEndMapper); sphereEnd->GetProperty()->SetColor(colors->GetColor3d("Magenta").GetData()); //Create a renderer, render window, and interactor vtkSmartPointer<vtkOpenVRRenderer> renderer = vtkSmartPointer<vtkOpenVRRenderer>::New(); vtkSmartPointer<vtkOpenVRRenderWindow> renderWindow = vtkSmartPointer<vtkOpenVRRenderWindow>::New(); renderWindow->AddRenderer(renderer); vtkSmartPointer<vtkOpenVRRenderWindowInteractor> renderWindowInteractor = vtkSmartPointer<vtkOpenVRRenderWindowInteractor>::New(); renderWindowInteractor->SetRenderWindow(renderWindow); //Add the actor to the scene renderer->AddActor(actor); renderer->AddActor(sphereStart); renderer->AddActor(sphereEnd); renderer->SetBackground(colors->GetColor3d("BkgColor").GetData()); //Render and interact renderWindow->Render(); renderWindowInteractor->Start(); return EXIT_SUCCESS; }
CMakeLists.txt¶
cmake_minimum_required(VERSION 2.8) PROJECT(OpenVROrientedArrow) find_package(VTK REQUIRED) include(${VTK_USE_FILE}) add_executable(OpenVROrientedArrow MACOSX_BUNDLE OpenVROrientedArrow.cxx ) target_link_libraries(OpenVROrientedArrow ${VTK_LIBRARIES})
Download and Build OpenVROrientedArrow¶
Click here to download OpenVROrientedArrow and its CMakeLists.txt file. Once the tarball OpenVROrientedArrow.tar has been downloaded and extracted,
cd OpenVROrientedArrow/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:
./OpenVROrientedArrow
WINDOWS USERS
Be sure to add the VTK bin directory to your path. This will resolve the VTK dll's at run time.