OpenVR - IVRSystem::GetControllerState 总是 returns 空结构

OpenVR - IVRSystem::GetControllerState always returns empty structs

我一直在关注 Kamran Bigdely-Shamloo 的 article on how to get positional information from the HTC Vive and it has worked well so far. My next step was to "listen" to button presses. I've read the documentation and it says here,我需要做的就是查询 IVRSystem::GetControllerState 它会 return 一个

"struct with the current state of the controller"

然而,此结构始终包含具有 0 值的变量。在 main 函数的 while (true) 循环中调用以下函数。

bool CMainApplication::HandleInput()
{
SDL_Event sdlEvent;
bool bRet = false;

while ( SDL_PollEvent( &sdlEvent ) != 0 )
{
    if ( sdlEvent.type == SDL_QUIT )
    {
        bRet = true;
    }
    else if ( sdlEvent.type == SDL_KEYDOWN )
    {
        if ( sdlEvent.key.keysym.sym == SDLK_ESCAPE 
             || sdlEvent.key.keysym.sym == SDLK_q )
        {
            bRet = true;
        }
        if( sdlEvent.key.keysym.sym == SDLK_c )
        {
            m_bShowCubes = !m_bShowCubes;
        }
    }
}

// Process SteamVR events
// Periodically returns an event of type 404 ("VREvent_SceneApplicationChanged      = 404, // data is process - The App actually drawing the scene changed (usually to or from the compositor)"
vr::VREvent_t event;
vr::VREvent_Controller_t controllerEvent;
std::chrono::milliseconds ms4;
while( m_pHMD->PollNextEvent( &event, sizeof( event ) ) )
{
    ms4 = std::chrono::duration_cast<std::chrono::milliseconds>(
        std::chrono::system_clock::now().time_since_epoch()
        );
    ProcessVREvent( &event);
    printPositionalData(&event, ms4);
}

vr::VRControllerState_t state;

// Check every device attached, usually it's four devices
// Second if statement is never reached
for (int i = 0; i < 1000; i++) {
    if (m_pHMD->GetControllerState(i, &state, sizeof(state))) {
        dprintf("%d", i);
            if (state.ulButtonPressed != 0 || state.unPacketNum != 0 || state.ulButtonTouched != 0) {
                dprintf("Some action?");
            }
    }
}
dprintf("\n");

// Process SteamVR action state
// UpdateActionState is called each frame to update the state of the actions themselves. The application
// controls which action sets are active with the provided array of VRActiveActionSet_t structs.
vr::VRActiveActionSet_t actionSet = { 0 };
actionSet.ulActionSet = m_actionsetDemo;
vr::VRInput()->UpdateActionState( &actionSet, sizeof(actionSet), 1 );

m_bShowCubes = !GetDigitalActionState( m_actionHideCubes );

vr::VRInputValueHandle_t ulHapticDevice;
if ( GetDigitalActionRisingEdge( m_actionTriggerHaptic, &ulHapticDevice ) )
{
    if ( ulHapticDevice == m_rHand[Left].m_source )
    {
        vr::VRInput()->TriggerHapticVibrationAction( m_rHand[Left].m_actionHaptic, 0, 1, 4.f, 1.0f, vr::k_ulInvalidInputValueHandle );
    }
    if ( ulHapticDevice == m_rHand[Right].m_source )
    {
        vr::VRInput()->TriggerHapticVibrationAction( m_rHand[Right].m_actionHaptic, 0, 1, 4.f, 1.0f, vr::k_ulInvalidInputValueHandle );
    }
}

vr::InputAnalogActionData_t analogData;
if ( vr::VRInput()->GetAnalogActionData( m_actionAnalongInput, &analogData, sizeof( analogData ), vr::k_ulInvalidInputValueHandle ) == vr::VRInputError_None && analogData.bActive )
{
    m_vAnalogValue[0] = analogData.x;
    m_vAnalogValue[1] = analogData.y;
}

m_rHand[Left].m_bShowController = true;
m_rHand[Right].m_bShowController = true;

vr::VRInputValueHandle_t ulHideDevice;
if ( GetDigitalActionState( m_actionHideThisController, &ulHideDevice ) )
{
    if ( ulHideDevice == m_rHand[Left].m_source )
    {
        m_rHand[Left].m_bShowController = false;
    }
    if ( ulHideDevice == m_rHand[Right].m_source )
    {
        m_rHand[Right].m_bShowController = false;
    }
}

for ( EHand eHand = Left; eHand <= Right; ((int&)eHand)++ )
{
    vr::InputPoseActionData_t poseData;
    if ( vr::VRInput()->GetPoseActionData( m_rHand[eHand].m_actionPose, vr::TrackingUniverseStanding, 0, &poseData, sizeof( poseData ), vr::k_ulInvalidInputValueHandle ) != vr::VRInputError_None
        || !poseData.bActive || !poseData.pose.bPoseIsValid )
    {
        m_rHand[eHand].m_bShowController = false;
    }
    else
    {
        m_rHand[eHand].m_rmat4Pose = ConvertSteamVRMatrixToMatrix4( poseData.pose.mDeviceToAbsoluteTracking );

        vr::InputOriginInfo_t originInfo;
        if ( vr::VRInput()->GetOriginTrackedDeviceInfo( poseData.activeOrigin, &originInfo, sizeof( originInfo ) ) == vr::VRInputError_None 
            && originInfo.trackedDeviceIndex != vr::k_unTrackedDeviceIndexInvalid )
        {
            std::string sRenderModelName = GetTrackedDeviceString( originInfo.trackedDeviceIndex, vr::Prop_RenderModelName_String );
            if ( sRenderModelName != m_rHand[eHand].m_sRenderModelName )
            {
                m_rHand[eHand].m_pRenderModel = FindOrLoadRenderModel( sRenderModelName.c_str() );
                m_rHand[eHand].m_sRenderModelName = sRenderModelName;
            }
        }
    }
}

return bRet;

m_pHMD初始化如下:

vr::IVRSystem *m_pHMD;
....
m_pHMD = vr::VR_Init( &eError, vr::VRApplication_Background );

我一定是做错了什么,因为在下面的代码片段中,if 语句仅在前四次迭代中传递,这应该是控制器、vive 跟踪器、耳机和灯塔。这告诉我我可以访问这些状态,但我无法以某种方式读取信息。

for (int i = 0; i < 1000; i++) {
    if (m_pHMD->GetControllerState(i, &state, sizeof(state))) {
        dprintf("%d", i);
            if (state.ulButtonPressed != 0 || state.unPacketNum != 0 || state.ulButtonTouched != 0) {
                dprintf("Some action?");
            }
    }

我无法想象这是一个错误,所以我猜测是我的配置有问题,或者我正在执行错误的查询。 非常感谢任何帮助!

显然我犯了两个错误。 错误 #1 是我使用了错误的样本文件。我使用了 OpenVr 示例文件夹中的 hellovr_opengl,但 hellovr_dx12 才是可行的解决方案。它也必须有不同类型的配置,因为我复制了一个正在工作的函数到 hellovr_opengl 项目中,但它没有工作!然后我复制了我添加到 hellovr_dx12 项目中的功能,并且能够获取 Vive 控制器的控制器状态。

但是,我想获取 Vive Tracker 的状态,但没有成功。经过一些谷歌搜索后,我发现了一个 issue with the current SteamVR driver,所以我将其恢复为 beta hoftix,这为我解决了 Vive Tracker 问题。

你要打电话;
vr::VRInput()->SetActionManifestPath