Commit 82803593 authored by Robin Eschbach's avatar Robin Eschbach
Browse files

[ADD #719] interaction with ROIs in VR

parent 54d328dd
......@@ -285,6 +285,7 @@ void WMVRCamera::handleControllerEvent( vr::VREvent_t vrEvent )
{
case vr::EVRButtonId::k_EButton_SteamVR_Trigger:
controller->setTriggered( pressed );
controller->setCurrentSelection( pressed ? findSelectedObject( controller ) : nullptr );
break;
case vr::EVRButtonId::k_EButton_Grip:
controller->setGripped( pressed );
......@@ -315,40 +316,171 @@ void WMVRCamera::updateControllerPoses()
m_leftController->updatePose( m_vrSystem, m_cameraPosition );
m_rightController->updatePose( m_vrSystem, m_cameraPosition );
// zooming
if( m_leftController->isTriggered() && m_rightController->isTriggered() )
{
double lenPrev = ( m_leftController->getPrevPosition() - m_rightController->getPrevPosition() ).length();
double lenNow = ( m_leftController->getPosition() - m_rightController->getPosition() ).length();
double length = lenNow - lenPrev;
if( m_leftController->getCurrentSelection() != nullptr )
{
handleResize();
}
else
{
handleZoom();
}
}
else if( m_rightController->isTriggered() )
{
handleGrab();
}
else if( m_leftController->isTriggered() )
{
handlePick();
}
if( m_leftController->isGripped() && m_rightController->isGripped() )
{
ResetHMDPosition();
}
}
void WMVRCamera::handleZoom()
{
double lenPrev = ( m_leftController->getPrevPosition() - m_rightController->getPrevPosition() ).length();
double lenNow = ( m_leftController->getPosition() - m_rightController->getPosition() ).length();
double length = lenNow - lenPrev;
osg::Vec3 dir( 0.0, 0.0, -1.0 );
dir = ( m_cameraRotation * m_HMD_rotation ) * dir;
dir *= length;
osg::Vec3 dir( 0.0, 0.0, -1.0 );
dir = ( m_cameraRotation * m_HMD_rotation ) * dir;
dir *= length;
m_cameraPosition += dir;
}
void WMVRCamera::handleGrab()
{
// data translation
osg::Vec3 diff = m_rightController->getPosition() - m_rightController->getPrevPosition();
m_dataPosition += diff;
// data rotation
osg::Vec3 contrPosition = ( m_cameraPosition - m_dataPosition ) + m_rightController->getPosition();
osg::Quat rotDiff = m_rightController->getPrevRotation().inverse() * m_rightController->getRotation();
osg::Matrixd rotMatrix = osg::Matrixd::translate( -contrPosition ) * osg::Matrixd::rotate( rotDiff ) * osg::Matrixd::translate( contrPosition );
m_dataRotation *= rotMatrix;
m_sceneTransform->setMatrix( m_dataRotation * osg::Matrixd::translate( m_dataPosition ) );
}
m_cameraPosition += dir;
std::string extractSuitableName( osgUtil::RayIntersector::Intersections::iterator hitr )
{
if( !hitr->nodePath.empty() && !( hitr->nodePath.back()->getName().empty() ) )
{
return hitr->nodePath.back()->getName();
}
else if( m_rightController->isTriggered() )
else if( hitr->drawable.valid() )
{
// data translation
osg::Vec3 diff = m_rightController->getPosition() - m_rightController->getPrevPosition();
m_dataPosition += diff;
return hitr->drawable->className();
}
assert( 0 && "This should not happen. Tell \"wiebel\" if it does." );
return ""; // This line will not be reached.
}
osg::Geode* WMVRCamera::findSelectedObject( WVRController* controller )
{
osg::Vec3 dir = controller->getRotation() * osg::Vec3( 0.0, 1.0, 0.0 );
osg::Vec3 pos = m_cameraPosition + controller->getPosition();
// data rotation
osg::Vec3 contrPosition = ( m_cameraPosition - m_dataPosition ) + m_rightController->getPosition();
osg::Quat rotDiff = m_rightController->getPrevRotation().inverse() * m_rightController->getRotation();
osg::Matrixd rotMatrix = osg::Matrixd::translate( -contrPosition ) * osg::Matrixd::rotate( rotDiff ) *
osg::Matrixd::translate( contrPosition );
osgUtil::RayIntersector::Intersections intersections;
m_dataRotation *= rotMatrix;
osg::ref_ptr< osgUtil::RayIntersector > picker = new osgUtil::RayIntersector( pos, dir );
osgUtil::IntersectionVisitor iv( picker.get() );
m_sceneTransform->setMatrix( m_dataRotation * osg::Matrixd::translate( m_dataPosition ) );
m_leftEyeCamera->accept( iv );
osgUtil::RayIntersector::Intersections::iterator hitr;
if( picker->containsIntersections() )
{
intersections = picker->getIntersections();
assert( intersections.size() );
hitr = intersections.begin();
while( hitr != intersections.end() )
{
std::string nodeName = extractSuitableName( hitr );
WAssert( nodeName.size() > 2, "Geode name too short for picking." );
// now we skip everything that starts with an underscores or vr
if( nodeName[0] == '_' || ( nodeName[0] == 'v' && nodeName[1] == 'r' ) )
{
++hitr;
}
else
{
return hitr->nodePath.back()->asGeode();
}
}
}
if( m_leftController->isGripped() && m_rightController->isGripped() )
return nullptr;
}
void WMVRCamera::handleResize()
{
WROIBox* roi = dynamic_cast< WROIBox* >( m_leftController->getCurrentSelection() );
if( !roi )
{
ResetHMDPosition();
return;
}
osg::Matrixd sceneMatrix = m_dataRotation * osg::Matrixd::translate( m_dataPosition );
osg::Vec3 maxPos = roi->getMaxPos();
maxPos = maxPos * sceneMatrix;
osg::Vec3 diff = m_rightController->getPosition() - m_rightController->getPrevPosition();
maxPos += diff;
maxPos = maxPos * osg::Matrixd::inverse( sceneMatrix );
roi->getMaxPosProperty()->set( WPosition( maxPos ) );
}
void WMVRCamera::handlePick()
{
if( m_leftController->getCurrentSelection() == nullptr )
{
return;
}
WROIBox* roi = dynamic_cast< WROIBox* >( m_leftController->getCurrentSelection() );
if( !roi )
{
return;
}
osg::Matrixd sceneMatrix = m_dataRotation * osg::Matrixd::translate( m_dataPosition );
osg::Vec3 sizeHalf( ( roi->getMaxPos() - roi->getMinPos() ) * 0.5 );
osg::Vec3 center( roi->getMinPos() );
center += sizeHalf;
center = center * sceneMatrix;
osg::Vec3 diff = m_leftController->getPosition()- m_leftController->getPrevPosition();
center += diff;
osg::Vec3 contrPosition = m_cameraPosition + m_leftController->getPosition();
osg::Quat rotDiff = m_leftController->getPrevRotation().inverse() * m_leftController->getRotation();
osg::Matrixd rotMatrix = osg::Matrixd::translate( -contrPosition ) * osg::Matrixd::rotate( rotDiff ) * osg::Matrixd::translate( contrPosition );
center = center * rotMatrix;
center = center * osg::Matrixd::inverse( sceneMatrix );
osg::Vec3 minPos = center- sizeHalf;
osg::Vec3 maxPos = center + sizeHalf;
roi->getMinPosProperty()->set( WPosition( minPos ) );
roi->getMaxPosProperty()->set( WPosition( maxPos ) );
}
void WMVRCamera::updateHMDPose()
......
......@@ -29,8 +29,11 @@
#include <openvr.h> // NOLINT
#include <osgUtil/RayIntersector>
#include "core/common/math/WMath.h"
#include "core/kernel/WModule.h"
#include "core/graphicsEngine/WROIBox.h"
#include "WRTTCamera.h"
#include "WSwapUpdateCallback.h"
......@@ -177,6 +180,34 @@ protected:
bool setupVRInterface();
private:
/**
* Handles the zoom interaction.
*/
void handleZoom();
/**
* Handles the grab interaction.
*/
void handleGrab();
/**
* Handles the pick interaction.
*/
void handlePick();
/**
* Handles the resize interaction.
*/
void handleResize();
/**
* Finds the object the controller is pointing at.
*
* \param controller The controller that points.
* \return osg::Geode* The object that is pointed at.
*/
osg::Geode* findSelectedObject( WVRController* controller );
std::shared_ptr< WCondition > m_propCondition; //!< A condition for property updates.
WPropBool m_vrOn; //!< A feature toggle for submitting frames to OpenVR SDK
......
......@@ -48,11 +48,21 @@ void WVRController::setGripped( bool gripped )
m_gripped = gripped;
}
void WVRController::setCurrentSelection( osg::Geode* selection )
{
m_currentSelection = selection;
}
uint32_t WVRController::getDeviceID()
{
return m_deviceID;
}
osg::Geode* WVRController::getCurrentSelection()
{
return m_currentSelection;
}
osg::ref_ptr< osg::Node > WVRController::getNode()
{
return m_node;
......@@ -138,8 +148,28 @@ void WVRController::createGeometry( std::string path )
{
osg::ref_ptr< osg::Node > controllerNode = osgDB::readNodeFile( path );
// handle direction
m_directionIndicator = new osg::Geode();
osg::Geometry* geo = new osg::Geometry();
osg::Vec4Array* v = new osg::Vec4Array();
osg::Vec4Array* c = new osg::Vec4Array();
v->push_back( osg::Vec4( 0.0, 0.0, 0.0, 1.0 ) );
v->push_back( osg::Vec4( 0.0, 1.0, 0.0, 0.0 ) );
c->push_back( osg::Vec4( 0.0, 0.0, 0.0, 1.0 ) );
c->push_back( osg::Vec4( 0.0, 0.0, 0.0, 1.0 ) );
geo->setVertexArray( v );
geo->setColorArray( c );
geo->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::LINES, 0, v->size() ) );
m_directionIndicator->addDrawable( geo );
// handle transform
osg::ref_ptr< osg::MatrixTransform > mat = osg::ref_ptr< osg::MatrixTransform >( new osg::MatrixTransform() );
mat->addChild( controllerNode );
mat->addChild( m_directionIndicator );
mat->setNodeMask( 0 );
......
......@@ -68,12 +68,24 @@ public:
*/
void setGripped( bool gripped );
/**
* Sets the current selection.
* \param selection The new selection.
*/
void setCurrentSelection( osg::Geode* selection );
/**
* Gets the device id
* \return int the device id.
*/
uint32_t getDeviceID();
/**
* Gets the current selection.
* \return osg::Geode* The current selection.
*/
osg::Geode* getCurrentSelection();
/**
* Gets the geometry node of the controller
* \return osg::ref_ptr< osg::Node > The node.
......@@ -136,8 +148,10 @@ private:
uint32_t m_deviceID; //!< The device id of the controller
osg::ref_ptr< osg::Node > m_node; //!< The geometry of the controller.
osg::ref_ptr< osg::Geode > m_directionIndicator; //!< The indicator for the direction.
osg::Vec3 m_position; //!< The current position of the controller relative to the camera position.
osg::Quat m_rotation; //!< The current rotation of the controller.
osg::Vec3 m_prevPosition; //!< The position of the previous frame.
......@@ -145,6 +159,8 @@ private:
bool m_triggered; //!< Whether the trigger button is pressed or not.
bool m_gripped; //!< Whether the grip button is pressed or not.
osg::Geode* m_currentSelection; // The current selection for the left controller.
};
#endif // WVRCONTROLLER_H
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment