diff --git a/Examples/OpenVRController/CMakeLists.txt b/Examples/OpenVRController/CMakeLists.txt index b22e1eee19c3b506f452a976f4960d1e649edaa9..5190298dac6aab05718309664d690b6d7b161c03 100644 --- a/Examples/OpenVRController/CMakeLists.txt +++ b/Examples/OpenVRController/CMakeLists.txt @@ -21,7 +21,10 @@ project(Example-OpenVRController) #----------------------------------------------------------------------------- # Create executable #----------------------------------------------------------------------------- -imstk_add_executable(${PROJECT_NAME} OpenVRControllerExample.cpp) +imstk_add_executable(${PROJECT_NAME} + OpenVRControllerExample.cpp + CameraOpenVRControl.h + CameraOpenVRControl.cpp) #----------------------------------------------------------------------------- # Add the target to Examples folder diff --git a/Examples/OpenVRController/CameraOpenVRControl.cpp b/Examples/OpenVRController/CameraOpenVRControl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fc2aa9663a1c53df7190a42f127427266f8559e9 --- /dev/null +++ b/Examples/OpenVRController/CameraOpenVRControl.cpp @@ -0,0 +1,60 @@ +/*========================================================================= + + Library: iMSTK + + Copyright (c) Kitware, Inc. & Center for Modeling, Simulation, + & Imaging in Medicine, Rensselaer Polytechnic Institute. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0.txt + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +=========================================================================*/ + +#include "CameraOpenVRControl.h" +#include "imstkCamera.h" +#include "imstkLogger.h" +#include "imstkOpenVRDeviceClient.h" + +using namespace imstk; + +void +CameraOpenVRControl::printControls() +{ + LOG(INFO) << "Mouse Scene Controls: Only usable in debug mode"; + LOG(INFO) << "----------------------------------------------------------------------"; + LOG(INFO) << " | Left Trackpad - rotate view"; + LOG(INFO) << " | Right Trakcpad - translate view"; + LOG(INFO) << "----------------------------------------------------------------------"; +} + +void +CameraOpenVRControl::update(const double dt) +{ + // We may switch cameras on the controller + if (m_camera == nullptr) + { + return; + } + + if (m_rotateDevice != nullptr) + { + const Vec2d& pos = m_rotateDevice->getTrackpadPosition(); + const Mat4d& view = m_camera->getView(); + m_camera->setView(view * mat4dRotation(Rotd(-pos[0] * m_rotateSpeedScale * dt, Vec3d(0.0, 1.0, 0.0)))); + } + if (m_translateDevice != nullptr) + { + const Vec2d& pos = m_translateDevice->getTrackpadPosition(); + const Mat4d& view = m_camera->getView(); + m_camera->setView(view * mat4dTranslate(Vec3d(pos[0], 0.0, -pos[1]) * m_translateSpeedScale * dt)); + } +} \ No newline at end of file diff --git a/Examples/OpenVRController/CameraOpenVRControl.h b/Examples/OpenVRController/CameraOpenVRControl.h new file mode 100644 index 0000000000000000000000000000000000000000..ed74ff89c548e56b2d09fb5940bc3324e6bba55f --- /dev/null +++ b/Examples/OpenVRController/CameraOpenVRControl.h @@ -0,0 +1,96 @@ +/*========================================================================= + + Library: iMSTK + + Copyright (c) Kitware, Inc. & Center for Modeling, Simulation, + & Imaging in Medicine, Rensselaer Polytechnic Institute. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0.txt + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +=========================================================================*/ + +#pragma once + +#include "imstkDeviceControl.h" +#include "imstkMath.h" + +namespace imstk +{ +class Camera; +class OpenVRDeviceClient; +class SceneManager; +} + +using namespace imstk; + +/// +/// \class CameraOpenVRControl +/// +/// \brief Controls pose of a camera given two trackpads from OpenVRDeviceClient's +/// +/// +class CameraOpenVRControl : public DeviceControl +{ +public: + CameraOpenVRControl() = default; + virtual ~CameraOpenVRControl() override = default; + +public: + /// + /// \brief Get/Set how fast the camera translates + /// + void setTranslateSpeedScale(const double translateSpeedScale) { m_translateSpeedScale = translateSpeedScale; } + double getTranslateSpeedScale() const { return m_translateSpeedScale; } + + /// + /// \brief Get/Set how fast the camera rotates + /// + void setRotateSpeedScale(const double rotateSpeedScale) { m_rotateSpeedScale = rotateSpeedScale; } + double getRotateSpeedScale() const { return m_rotateSpeedScale; } + + /// + /// \brief Get/Set the device that can translate the camera + /// + void setTranslateDevice(std::shared_ptr<OpenVRDeviceClient> translateDevice) { m_translateDevice = translateDevice; } + std::shared_ptr<OpenVRDeviceClient> getTranslateDevice() const { return m_translateDevice; } + + /// + /// \brief Get/Set the device that can rotate the camera + /// + void setRotateDevice(std::shared_ptr<OpenVRDeviceClient> rotateDevice) { m_rotateDevice = rotateDevice; } + std::shared_ptr<OpenVRDeviceClient> getRotateDevice() const { return m_rotateDevice; } + + /// + /// \brief Get/Set the camera to be controlled + /// + void setCamera(std::shared_ptr<Camera> camera) { m_camera = camera; } + std::shared_ptr<Camera> getCamera() const { return m_camera; } + +public: + void printControls() override; + + /// + /// \brief Updates control based on current device state + /// + void update(const double dt) override; + +protected: + std::shared_ptr<OpenVRDeviceClient> m_translateDevice = nullptr; + std::shared_ptr<OpenVRDeviceClient> m_rotateDevice = nullptr; + + std::shared_ptr<Camera> m_camera = nullptr; + + // User changeable values + double m_rotateSpeedScale = 1.0; + double m_translateSpeedScale = 1.0; +}; \ No newline at end of file diff --git a/Examples/OpenVRController/OpenVRControllerExample.cpp b/Examples/OpenVRController/OpenVRControllerExample.cpp index e0b66c2a91f3f23f5a375bc37d8490b84c1f2eb2..cc612e79b88e34df225c6886da166e6fcd2f2ac4 100644 --- a/Examples/OpenVRController/OpenVRControllerExample.cpp +++ b/Examples/OpenVRController/OpenVRControllerExample.cpp @@ -35,6 +35,10 @@ #include "imstkVisualModel.h" #include "imstkVisualObjectImporter.h" #include "imstkVTKOpenVRViewer.h" +#include "CameraOpenVRControl.h" +#include "imstkVTKViewer.h" + +#include "imstkTimer.h" using namespace imstk; @@ -125,80 +129,111 @@ main() { // Add a module to run the viewer - imstkNew<VTKOpenVRViewer> viewer; + imstkNew<VTKViewer> viewer; + viewer->setExecutionType(Module::ExecutionType::SEQUENTIAL); viewer->setActiveScene(scene); // Add a module to run the scene - imstkNew<SceneManager> sceneManager; - sceneManager->setActiveScene(scene); + /*imstkNew<SceneManager> sceneManager; + sceneManager->setActiveScene(scene);*/ imstkNew<SimulationManager> driver; driver->addModule(viewer); - driver->addModule(sceneManager); - - // Add a VR controller for the scalpel handle - imstkNew<SceneObjectController> controller1(scalpelHandle, viewer->getVRDeviceClient(OPENVR_RIGHT_CONTROLLER)); - scene->addController(controller1); - // Add a VR controller for the scalpel blade - imstkNew<SceneObjectController> controller2(scalpelBlade10, viewer->getVRDeviceClient(OPENVR_RIGHT_CONTROLLER)); - scene->addController(controller2); - - // This button event is emitted from the viewer's thread, thus it is queued to the scene so that we do not - // run it while the scene is updating - bool blade10InHand = true; - queueConnect<ButtonEvent>(viewer->getVRDeviceClient(OPENVR_RIGHT_CONTROLLER), &OpenVRDeviceClient::buttonStateChanged, sceneManager, - [&](ButtonEvent* e) + //driver->addModule(sceneManager); + //driver->setDesiredDt(0.01); + + //// Add a VR controller for the scalpel handle + //imstkNew<SceneObjectController> controller1(scalpelHandle, viewer->getVRDeviceClient(OPENVR_RIGHT_CONTROLLER)); + //scene->addController(controller1); + //// Add a VR controller for the scalpel blade + //imstkNew<SceneObjectController> controller2(scalpelBlade10, viewer->getVRDeviceClient(OPENVR_RIGHT_CONTROLLER)); + //scene->addController(controller2); + + //imstkNew<CameraOpenVRControl> camControl; + //camControl->setRotateDevice(viewer->getVRDeviceClient(OPENVR_RIGHT_CONTROLLER)); + //camControl->setTranslateDevice(viewer->getVRDeviceClient(OPENVR_LEFT_CONTROLLER)); + //camControl->setTranslateSpeedScale(1.0); + //camControl->setRotateSpeedScale(1.0); + //camControl->setCamera(scene->getActiveCamera()); + //viewer->addControl(camControl); // Only needs to update every render + + StopWatch timer; + timer.start(); + int i = 0; + //connect<Event>(viewer, &Viewer::postUpdate, [&](Event*) + // { + // double ms = timer.getTimeElapsed(); + // //if (i++ % 100 == 0) + // { + // printf("%f\n", ms); + // } + // timer.start(); + // }); + viewer->init(); + while(true) { - // When any button pressed, swap blade - if (e->m_buttonState == BUTTON_PRESSED) - { - const Vec3d& posControl = viewer->getVRDeviceClient(OPENVR_RIGHT_CONTROLLER)->getPosition(); - if (blade10InHand) - { - // Swap to blade 15 only if it's close in space - Vec3d min, max; - scalpelBlade15->getVisualGeometry()->computeBoundingBox(min, max); - const Vec3d posBlade = (min + max) * 0.5; - const double dist = (posControl - posBlade).norm(); - LOG(INFO) << "Dist: " << dist; - if (dist < 2.0) - { - const Vec3d t = scalpelBlade15->getVisualGeometry()->getTranslation(); - const Mat3d r = scalpelBlade15->getVisualGeometry()->getRotation(); - - // Set the new blade to move - controller2->setControlledSceneObject(scalpelBlade15); - blade10InHand = false; - - scalpelBlade10->getVisualGeometry()->setTranslation(t); - scalpelBlade10->getVisualGeometry()->setRotation(r); - } - } - else - { - // Swap to blade 10 only if it's close in space - Vec3d min, max; - scalpelBlade10->getVisualGeometry()->computeBoundingBox(min, max); - const Vec3d posBlade = (min + max) * 0.5; - const double dist = (posControl - posBlade).norm(); - LOG(INFO) << "Dist: " << dist; - if (dist < 2.0) - { - const Vec3d t = scalpelBlade10->getVisualGeometry()->getTranslation(); - const Mat3d r = scalpelBlade10->getVisualGeometry()->getRotation(); - - controller2->setControlledSceneObject(scalpelBlade10); - blade10InHand = true; - - // Swap transforms of the blades - scalpelBlade15->getVisualGeometry()->setTranslation(t); - scalpelBlade15->getVisualGeometry()->setRotation(r); - } - } - } - }); - - driver->start(); + double ms = timer.getTimeElapsed(); + printf("%f\n", ms); + timer.start(); + viewer->update(); + } + + //// This button event is emitted from the viewer's thread, thus it is queued to the scene so that we do not + //// run it while the scene is updating + //bool blade10InHand = true; + //queueConnect<ButtonEvent>(viewer->getVRDeviceClient(OPENVR_RIGHT_CONTROLLER), &OpenVRDeviceClient::buttonStateChanged, sceneManager, + // [&](ButtonEvent* e) + //{ + // // When any button pressed, swap blade + // if (e->m_buttonState == BUTTON_PRESSED) + // { + // const Vec3d& posControl = viewer->getVRDeviceClient(OPENVR_RIGHT_CONTROLLER)->getPosition(); + // if (blade10InHand) + // { + // // Swap to blade 15 only if it's close in space + // Vec3d min, max; + // scalpelBlade15->getVisualGeometry()->computeBoundingBox(min, max); + // const Vec3d posBlade = (min + max) * 0.5; + // const double dist = (posControl - posBlade).norm(); + // LOG(INFO) << "Dist: " << dist; + // if (dist < 2.0) + // { + // const Vec3d t = scalpelBlade15->getVisualGeometry()->getTranslation(); + // const Mat3d r = scalpelBlade15->getVisualGeometry()->getRotation(); + + // // Set the new blade to move + // controller2->setControlledSceneObject(scalpelBlade15); + // blade10InHand = false; + + // scalpelBlade10->getVisualGeometry()->setTranslation(t); + // scalpelBlade10->getVisualGeometry()->setRotation(r); + // } + // } + // else + // { + // // Swap to blade 10 only if it's close in space + // Vec3d min, max; + // scalpelBlade10->getVisualGeometry()->computeBoundingBox(min, max); + // const Vec3d posBlade = (min + max) * 0.5; + // const double dist = (posControl - posBlade).norm(); + // LOG(INFO) << "Dist: " << dist; + // if (dist < 2.0) + // { + // const Vec3d t = scalpelBlade10->getVisualGeometry()->getTranslation(); + // const Mat3d r = scalpelBlade10->getVisualGeometry()->getRotation(); + + // controller2->setControlledSceneObject(scalpelBlade10); + // blade10InHand = true; + + // // Swap transforms of the blades + // scalpelBlade15->getVisualGeometry()->setTranslation(t); + // scalpelBlade15->getVisualGeometry()->setRotation(r); + // } + // } + // } + //}); + + //driver->start(); } return 0;