Commit ad28a29d authored by Jean-Baptiste Vimort's avatar Jean-Baptiste Vimort
Browse files

ENH: Integration of openVR in iMSTK

The simulation can now be set to either instantiate:
  - A regular simulation using vtkRenderWindow
  - A VR simulation using vtkOpenVRRenderWindow

To do so, the simulation manager can be set to be a VR simulation
when initialized. The default comportment will be a regular simulation.
parent 4882a321
......@@ -119,5 +119,6 @@ ExternalProject_Add( ${PROJECT_NAME}
-DODE_ROOT_DIR:PATH=${ODE_ROOT_DIR}
-D${PROJECT_NAME}_USE_Vulkan:BOOL=${${PROJECT_NAME}_USE_Vulkan}
-D${PROJECT_NAME}_ENABLE_AUDIO:BOOL=${${PROJECT_NAME}_ENABLE_AUDIO}
-D${PROJECT_NAME}_ENABLE_VR:BOOL=${${PROJECT_NAME}_ENABLE_VR}
DEPENDS ${${PROJECT_NAME}_DEPENDENCIES}
)
#-----------------------------------------------------------------------------
# Dependencies
#-----------------------------------------------------------------------------
set(VTK_DEPENDENCIES "")
if(${${PROJECT_NAME}_ENABLE_VR})
list(APPEND VTK_DEPENDENCIES "openvr")
endif(${${PROJECT_NAME}_ENABLE_VR})
#-----------------------------------------------------------------------------
# Add External Project
#-----------------------------------------------------------------------------
include(imstkAddExternalProject)
imstk_add_external_project( VTK
GIT_REPOSITORY https://gitlab.kitware.com/vtk/vtk.git
GIT_TAG 7b563776b89f829b382ba080d8963a04d7a47ecc
GIT_TAG 1258310c753261146771f1e5fbc5c23f90ec7341
INSTALL_COMMAND ${SKIP_STEP_COMMAND}
CMAKE_ARGS
-DBUILD_EXAMPLES:BOOL=OFF
......@@ -18,12 +26,14 @@ imstk_add_external_project( VTK
-DModule_vtkIOGeometry:BOOL=ON
-DModule_vtkInteractionStyle:BOOL=ON
-DModule_vtkRenderingAnnotation:BOOL=ON
-DModule_vtkRenderingOpenVR:BOOL=${${PROJECT_NAME}_ENABLE_VR}
-DModule_vtkInteractionWidgets:BOOL=ON
-DModule_vtkglew:BOOL=ON
-DModule_vtkRenderingContext2D:BOOL=ON
-DVTK_RENDERING_BACKEND:STRING=OpenGL2
-DVTK_WRAP_PYTHON:BOOL=OFF
-DVTK_OPENVR_OBJECT_FACTORY:BOOL=OFF
DEPENDENCIES ${VTK_DEPENDENCIES}
RELATIVE_INCLUDE_PATH ""
DEPENDENCIES ""
#VERBOSE
)
if(NOT WIN32)
message(WARNING "System not supported. For nownly Windows is supported for External_OPENVR.cmake.")
return()
endif()
set(_version "1.0.9")
#-----------------------------------------------------------------------------
# Set project prefix path
#-----------------------------------------------------------------------------
set(OPENVR_PREFIX ${CMAKE_BINARY_DIR}/External/openvr)
set(OPENVR_EXTRACT_DIR ${OPENVR_PREFIX}/v${_version})
#-----------------------------------------------------------------------------
# Set install commands
#-----------------------------------------------------------------------------
if(WIN32)
set(openvr_libdir "${OPENVR_EXTRACT_DIR}/lib/win64")
set(openvr_libname "openvr_api.lib")
elseif(APPLE)
set(openvr_libdir "${OPENVR_EXTRACT_DIR}/lib/osx32")
set(openvr_libname "libopenvr_api.dylib")
elseif(UNIX)
set(openvr_libdir "${OPENVR_EXTRACT_DIR}/lib/linux64")
set(openvr_libname "libopenvr_api.so")
endif()
if(WIN32)
set(openvr_dlldir "${OPENVR_EXTRACT_DIR}/bin/win64")
set(openvr_dllname "openvr_api.dll")
elseif(APPLE)
set(openvr_dlldir "${OPENVR_EXTRACT_DIR}/bin/osx64")
set(openvr_dllname "OpenVR.framework")
elseif(UNIX)
set(openvr_dlldir "${OPENVR_EXTRACT_DIR}/bin/linux64")
set(openvr_dllname "libopenvr_api.so")
endif()
set(copy_openvr_dll_command
${CMAKE_COMMAND} -E copy
${openvr_dlldir}/${openvr_dllname}
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR}/${openvr_dllname}
)
set(copy_openvr_lib_command
${CMAKE_COMMAND} -E copy
${openvr_libdir}/${openvr_libname}
${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR}/${openvr_libname}
)
#-----------------------------------------------------------------------------
# Add External Project
#-----------------------------------------------------------------------------
include(imstkAddExternalProject)
imstk_add_external_project( openvr
URL "https://github.com/ValveSoftware/openvr/archive/v${_version}.tar.gz"
URL_MD5 "0de39e805155cf4e0e907bb181924c48"
DOWNLOAD_DIR ${OPENVR_PREFIX}
SOURCE_DIR ${OPENVR_EXTRACT_DIR}
BINARY_DIR ${OPENVR_EXTRACT_DIR}
UPDATE_COMMAND ${SKIP_STEP_COMMAND}
CONFIGURE_COMMAND ${SKIP_STEP_COMMAND}
BUILD_COMMAND ${SKIP_STEP_COMMAND}
INSTALL_COMMAND
${copy_openvr_lib_command}
COMMAND ${copy_openvr_dll_command}
RELATIVE_INCLUDE_PATH "headers"
#VERBOSE
)
......@@ -106,6 +106,12 @@ if(${PROJECT_NAME}_SUPERBUILD)
imstk_define_dependency(gli)
endif()
option(${PROJECT_NAME}_ENABLE_VR "Allow the usage of VR rendering." OFF)
if(${PROJECT_NAME}_ENABLE_VR)
imstk_define_dependency(openvr)
endif()
if(WIN32)
imstk_define_dependency(PThreads)
imstk_define_dependency(Libusb) #for VRPN
......@@ -236,6 +242,12 @@ if( ${PROJECT_NAME}_USE_Vulkan )
include_directories( ${gli_INCLUDE_DIR} )
endif()
if(${PROJECT_NAME}_ENABLE_VR)
add_definitions( -DiMSTK_ENABLE_VR )
else()
remove_definitions( -DiMSTK_ENABLE_VR )
endif()
# g3log
find_package( g3log REQUIRED )
include_directories( ${g3log_INCLUDE_DIR} )
......
......@@ -35,9 +35,22 @@
namespace imstk
{
VTKRenderer::VTKRenderer(std::shared_ptr<Scene> scene)
VTKRenderer::VTKRenderer(std::shared_ptr<Scene> scene, bool enableVR)
{
m_scene = scene;
// create m_vtkRenderer depending on enableVR
if (!enableVR)
{
m_vtkRenderer = vtkSmartPointer<vtkRenderer>::New();
}
#ifdef iMSTK_ENABLE_VR
else
{
m_vtkRenderer = vtkSmartPointer<vtkOpenVRRenderer>::New();
}
#endif
this->updateRenderDelegates();
// Initialize textures for surface mesh render delegates
......@@ -70,15 +83,37 @@ VTKRenderer::VTKRenderer(std::shared_ptr<Scene> scene)
m_debugVtkActors.push_back( axes );
// Camera and camera actor
m_sceneVtkCamera = vtkSmartPointer<vtkCamera>::New();
if (!enableVR)
{
m_sceneVtkCamera = vtkSmartPointer<vtkCamera>::New();
}
#ifdef iMSTK_ENABLE_VR
else
{
m_sceneVtkCamera = vtkSmartPointer<vtkOpenVRCamera>::New();
}
#endif
this->updateSceneCamera(scene->getCamera());
auto camActor = vtkSmartPointer<vtkCameraActor>::New();
camActor->SetCamera( m_sceneVtkCamera );
m_debugVtkActors.push_back( camActor );
// Debug camera
m_defaultVtkCamera = m_vtkRenderer->GetActiveCamera();
if (!enableVR)
{
m_defaultVtkCamera = m_vtkRenderer->GetActiveCamera();
m_vtkRenderer->ResetCamera();
}
#ifdef iMSTK_ENABLE_VR
else
{
// in VR mode, we keep m_defaultVtkCamera as the HMD camera
// => Do not change the active Camera
m_defaultVtkCamera = vtkSmartPointer<vtkOpenVRCamera>::New();
m_vtkRenderer->SetActiveCamera(m_defaultVtkCamera);
}
#endif
///TODO : based on scene properties
// Customize background colors
m_vtkRenderer->SetBackground(0.66,0.66,0.66);
......@@ -92,7 +127,49 @@ VTKRenderer::VTKRenderer(std::shared_ptr<Scene> scene)
m_vtkRenderer->RemoveCuller(culler);
}
this->setMode(Mode::SIMULATION);
// set camera pos
#ifdef iMSTK_ENABLE_VR
if (enableVR)
{
m_camPos.resize(2);
// save debug camera m_camPos[0]
m_defaultVtkCamera->GetPosition(m_camPos[0].Position);
m_defaultVtkCamera->GetDirectionOfProjection(m_camPos[0].ViewDirection);
m_camPos[0].PhysicalViewUp[0] = 0.0;
m_camPos[0].PhysicalViewUp[1] = 1.0;
m_camPos[0].PhysicalViewUp[2] = 0.0;
m_camPos[0].PhysicalViewDirection[0] = 1.0;
m_camPos[0].PhysicalViewDirection[1] = 0.0;
m_camPos[0].PhysicalViewDirection[2] = 0.0;
m_camPos[0].Distance = 10; // room scale factor
m_camPos[0].Translation[0] = 0.0;
m_camPos[0].Translation[1] = 0.0;
m_camPos[0].Translation[2] = 0.0;
// save scene camera m_camPos[1]
m_sceneVtkCamera->GetPosition(m_camPos[1].Position);
m_sceneVtkCamera->GetDirectionOfProjection(m_camPos[1].ViewDirection);
m_camPos[1].PhysicalViewUp[0] = 0.0;
m_camPos[1].PhysicalViewUp[1] = 1.0;
m_camPos[1].PhysicalViewUp[2] = 0.0;
m_camPos[1].PhysicalViewDirection[0] = 1.0;
m_camPos[1].PhysicalViewDirection[1] = 0.0;
m_camPos[1].PhysicalViewDirection[2] = 0.0;
m_camPos[1].Distance = 1.0; // room scale factor of 1 meter
m_camPos[1].Translation[0] = 0.0;
m_camPos[1].Translation[1] = 0.0;
m_camPos[1].Translation[2] = 0.0;
}
#endif
}
vtkSmartPointer<vtkRenderer>
......@@ -102,8 +179,19 @@ VTKRenderer::getVtkRenderer() const
}
void
VTKRenderer::setMode(Renderer::Mode mode)
VTKRenderer::setMode(Renderer::Mode mode, bool enableVR)
{
#ifdef iMSTK_ENABLE_VR
vtkOpenVRRenderWindow* renWin = nullptr;
if (enableVR)
{
renWin = vtkOpenVRRenderWindow::SafeDownCast(m_vtkRenderer->GetRenderWindow());
if (!renWin || !m_vtkRenderer)
{
return;
}
}
#endif
if( mode == Mode::EMPTY && m_currentMode != Mode::EMPTY )
{
this->removeActors(m_objectVtkActors);
......@@ -113,8 +201,11 @@ VTKRenderer::setMode(Renderer::Mode mode)
{
this->removeActors(m_debugVtkActors);
}
m_vtkRenderer->SetActiveCamera(m_defaultVtkCamera);
// do not change active camera in VR
if (!enableVR)
{
m_vtkRenderer->SetActiveCamera(m_defaultVtkCamera);
}
}
else if( mode == Mode::DEBUG && m_currentMode != Mode::DEBUG )
{
......@@ -128,9 +219,20 @@ VTKRenderer::setMode(Renderer::Mode mode)
m_vtkRenderer->AddLight(light);
}
}
m_vtkRenderer->SetActiveCamera(m_defaultVtkCamera);
m_vtkRenderer->ResetCamera();
// do not change active camera in VR
if (!enableVR)
{
m_vtkRenderer->SetActiveCamera(m_defaultVtkCamera);
m_vtkRenderer->ResetCamera();
}
#ifdef iMSTK_ENABLE_VR
else // go to debug position camera
{
// apply debug camera
m_camPos[0].Apply(static_cast<vtkOpenVRCamera *>(m_vtkRenderer->GetActiveCamera()), renWin);
m_vtkRenderer->ResetCameraClippingRange();
}
#endif
}
else if ( mode == Mode::SIMULATION && m_currentMode != Mode::SIMULATION )
{
......@@ -145,13 +247,33 @@ VTKRenderer::setMode(Renderer::Mode mode)
else if( m_currentMode == Mode::DEBUG )
{
this->removeActors(m_debugVtkActors);
}
m_vtkRenderer->SetActiveCamera(m_sceneVtkCamera);
#ifdef iMSTK_ENABLE_VR
// save last debug position camera
if (enableVR)
{
m_camPos[0].Set(
static_cast<vtkOpenVRCamera *>(m_vtkRenderer->GetActiveCamera()),
vtkOpenVRRenderWindow::SafeDownCast(renWin));
}
#endif
}
// do not change active camera in VR
if (!enableVR)
{
m_vtkRenderer->SetActiveCamera(m_sceneVtkCamera);
}
#ifdef iMSTK_ENABLE_VR
else // go to Predefined sceneVtkCamera position
{
// apply scene camera
m_camPos[1].Apply(static_cast<vtkOpenVRCamera *>(m_vtkRenderer->GetActiveCamera()), renWin);
}
#endif
m_vtkRenderer->ResetCameraClippingRange();
}
m_currentMode = mode;
Renderer::setMode(mode, enableVR);
}
void
......
......@@ -36,6 +36,15 @@
#include "vtkCamera.h"
#include "vtkLight.h"
#ifdef iMSTK_ENABLE_VR
#include "vtkOpenVRRenderer.h"
#include "vtkOpenVRCamera.h"
#include "vtkOpenVRRenderWindow.h"
#include "vtkOpenVRRenderWindowInteractor.h"
#include "vtkInteractorStyle3D.h"
#include "vtkOpenVROverlayInternal.h"
#endif
namespace imstk
{
class Scene;
......@@ -53,7 +62,7 @@ public:
///
/// \brief Constructor
///
VTKRenderer(std::shared_ptr<Scene> scene);
VTKRenderer(std::shared_ptr<Scene> scene, bool enableVR);
///
/// \brief Default destructor
......@@ -64,7 +73,7 @@ public:
/// \brief Set/Get the rendering mode which defined the
/// visibility of the renderer actors and the default camera
///
virtual void setMode(Mode mode);
void setMode(Mode mode, bool enableVR) override;
///
/// \brief
......@@ -97,7 +106,7 @@ protected:
///
void addActors(const std::vector<vtkSmartPointer<vtkProp>>& actorList);
vtkSmartPointer<vtkRenderer> m_vtkRenderer = vtkSmartPointer<vtkRenderer>::New();
vtkSmartPointer<vtkRenderer> m_vtkRenderer;
vtkSmartPointer<vtkCamera> m_defaultVtkCamera;
vtkSmartPointer<vtkCamera> m_sceneVtkCamera;
std::vector<vtkSmartPointer<vtkLight>> m_vtkLights;
......@@ -109,6 +118,9 @@ protected:
std::shared_ptr<Scene> m_scene;
TextureManager<VTKTextureDelegate> m_textureManager;
#ifdef iMSTK_ENABLE_VR
std::vector<vtkOpenVRCameraPose> m_camPos;
#endif
};
}
......
......@@ -30,7 +30,7 @@ Renderer::getRenderer()
}
void
Renderer::setMode(Renderer::Mode mode)
Renderer::setMode(Renderer::Mode mode, bool enableVR)
{
m_currentMode = mode;
}
......
......@@ -50,7 +50,7 @@ public:
///
/// \brief Set rendering mode
///
virtual void setMode(Renderer::Mode mode);
virtual void setMode(Renderer::Mode mode, bool enableVR);
///
/// \brief Get rendering mode
......
......@@ -44,6 +44,7 @@ imstk_add_library( SimulationManager
imstkViewer.h
imstkScreenCaptureUtility.h
imstkInteractorStyle.h
imstkOpenVRCommand.h
${SIMULATIONMANAGER_H_FILES}
CPP_FILES
imstkSceneManager.cpp
......@@ -51,6 +52,7 @@ imstk_add_library( SimulationManager
imstkViewer.cpp
imstkScreenCaptureUtility.cpp
imstkInteractorStyle.cpp
imstkOpenVRCommand.cpp
${SIMULATIONMANAGER_CPP_FILES}
SUBDIR_LIST
${SIMULATIONMANAGER_SUBDIR}
......
......@@ -49,7 +49,7 @@ VTKScreenCaptureUtility::saveScreenShot()
{
m_windowToImageFilter->SetInput(m_renderWindow);
m_windowToImageFilter->SetMagnification(1);
m_windowToImageFilter->SetScale(1);
m_windowToImageFilter->SetInputBufferTypeToRGB();
m_windowToImageFilter->ReadFrontBufferOff();
m_windowToImageFilter->Update();
......
......@@ -51,7 +51,7 @@ VTKViewer::setActiveScene(std::shared_ptr<Scene>scene)
// Create renderer if it doesn't exist
if (!m_rendererMap.count(m_activeScene))
{
m_rendererMap[m_activeScene] = std::make_shared<VTKRenderer>(m_activeScene);
m_rendererMap[m_activeScene] = std::make_shared<VTKRenderer>(m_activeScene, m_enableVR);
}
// Cast to VTK renderer
......@@ -60,11 +60,14 @@ VTKViewer::setActiveScene(std::shared_ptr<Scene>scene)
// Set renderer to renderWindow
m_vtkRenderWindow->AddRenderer(vtkRenderer);
// Set renderer to interactorStyle
std::dynamic_pointer_cast<VTKInteractorStyle>(m_interactorStyle)->SetCurrentRenderer(vtkRenderer);
if (!m_enableVR)
{
// Set renderer to interactorStyle
std::dynamic_pointer_cast<VTKInteractorStyle>(m_interactorStyle)->SetCurrentRenderer(vtkRenderer);
// Set name to renderWindow
m_vtkRenderWindow->SetWindowName(m_activeScene->getName().data());
// Set name to renderWindow
m_vtkRenderWindow->SetWindowName(m_activeScene->getName().data());
}
}
void
......@@ -78,7 +81,7 @@ VTKViewer::setRenderingMode(Renderer::Mode mode)
}
// Setup renderer
this->getActiveRenderer()->setMode(mode);
this->getActiveRenderer()->setMode(mode, m_enableVR);
if (!m_running)
{
return;
......@@ -87,6 +90,10 @@ VTKViewer::setRenderingMode(Renderer::Mode mode)
// Render to update displayed actors
m_vtkRenderWindow->Render();
if (m_enableVR)
{
return;
}
// Setup render window
if (mode == Renderer::Mode::SIMULATION)
{
......@@ -113,10 +120,18 @@ void
VTKViewer::startRenderingLoop()
{
m_running = true;
m_vtkRenderWindow->GetInteractor()->Initialize();
m_vtkRenderWindow->GetInteractor()->CreateOneShotTimer(0);
m_vtkRenderWindow->GetInteractor()->Start();
m_vtkRenderWindow->GetInteractor()->DestroyTimer();
if (!m_enableVR)
{
m_vtkRenderWindow->GetInteractor()->Initialize();
m_vtkRenderWindow->GetInteractor()->CreateOneShotTimer(0);
m_vtkRenderWindow->GetInteractor()->Start();
m_vtkRenderWindow->GetInteractor()->DestroyTimer();
}
else
{
m_vtkRenderWindow->GetInteractor()->Start();
}
m_running = false;
}
......@@ -165,8 +180,8 @@ VTKViewer::setTargetFrameRate(const double& fps)
vtkInteractorStyle->m_targetMS = 0;
return;
}
vtkInteractorStyle->m_targetMS = 1000.0/fps;
std::cout << "Target framerate: " << fps << " (" << vtkInteractorStyle->m_targetMS << " ms)"<< std::endl;
vtkInteractorStyle->m_targetMS = 1000.0 / fps;
std::cout << "Target framerate: " << fps << " (" << vtkInteractorStyle->m_targetMS << " ms)" << std::endl;
}
......
......@@ -40,6 +40,12 @@
//Screenshot utility
#include "imstkVTKScreenCaptureUtility.h"
#ifdef iMSTK_ENABLE_VR
#include "imstkOpenVRCommand.h"
#include "vtkOpenVRRenderWindow.h"
#include "vtkOpenVRRenderWindowInteractor.h"
#endif
namespace imstk
{
class SimulationManager;
......@@ -55,15 +61,47 @@ public:
///
/// \brief Constructor
///
VTKViewer(SimulationManager* manager = nullptr)
VTKViewer(SimulationManager* manager = nullptr, bool enableVR = false)
{
m_interactorStyle = std::make_shared<VTKInteractorStyle>();
auto vtkInteractorStyle = std::dynamic_pointer_cast<VTKInteractorStyle>(m_interactorStyle);
vtkInteractorStyle->m_simManager = manager;
m_vtkRenderWindow->SetInteractor(m_vtkRenderWindow->MakeRenderWindowInteractor());
m_vtkRenderWindow->GetInteractor()->SetInteractorStyle( vtkInteractorStyle.get() );
m_vtkRenderWindow->SetSize(1000,800);
m_screenCapturer = std::make_shared<VTKScreenCaptureUtility>(m_vtkRenderWindow);
m_enableVR = enableVR;
// init render window / interactor / command based
// depending on if we enable VR or not
if (!m_enableVR)
{
// Interactor style / commands
m_interactorStyle = std::make_shared<VTKInteractorStyle>();
auto vtkInteractorStyle = std::dynamic_pointer_cast<VTKInteractorStyle>(m_interactorStyle);
vtkInteractorStyle->m_simManager = manager;
// Interactor
auto vtkInteractor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
vtkInteractor->SetInteractorStyle(vtkInteractorStyle.get());
// Render window
m_vtkRenderWindow = vtkSmartPointer<vtkRenderWindow>::New();
m_vtkRenderWindow->SetInteractor(vtkInteractor);
m_vtkRenderWindow->SetSize(1000, 800);
// Screen capture
m_screenCapturer = std::make_shared<VTKScreenCaptureUtility>(m_vtkRenderWindow);
}
#ifdef iMSTK_ENABLE_VR
else
{
// Interactor style / commands
m_openVRCommand = vtkSmartPointer<OpenVRCommand>::New();
m_openVRCommand->SetSimulationManager(manager);
// Interactor
auto vtkOpenVRinteractor = vtkSmartPointer<vtkOpenVRRenderWindowInteractor>::New();
// Add observer openVR command
m_vtkRenderWindow = vtkSmartPointer<vtkOpenVRRenderWindow>::New();
m_vtkRenderWindow->SetInteractor(vtkOpenVRinteractor);
vtkOpenVRinteractor->SetRenderWindow(m_vtkRenderWindow);
m_vtkRenderWindow->AddObserver(vtkCommand::StartEvent, m_openVRCommand, 1.0);
}
#endif
}
///
......@@ -124,7 +162,12 @@ public:
protected:
vtkSmartPointer<vtkRenderWindow> m_vtkRenderWindow = vtkSmartPointer<vtkRenderWindow>::New();
vtkSmartPointer<vtkRenderWindow> m_vtkRenderWindow;
bool m_enableVR;
#ifdef iMSTK_ENABLE_VR
vtkSmartPointer<OpenVRCommand> m_openVRCommand;
#endif
};
} // imstk
......
/*=========================================================================
Library: iMSTK