Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "device/vr/openvr/openvr_gamepad_data_fetcher.h" | |
| 6 | |
| 7 #include <memory> | |
| 8 | |
| 9 #include "base/logging.h" | |
| 10 #include "base/strings/utf_string_conversions.h" | |
| 11 #include "device/gamepad/public/cpp/gamepads.h" | |
| 12 #include "third_party/openvr/src/headers/openvr.h" | |
| 13 #include "ui/gfx/transform.h" | |
| 14 #include "ui/gfx/transform_util.h" | |
| 15 | |
| 16 namespace device { | |
| 17 | |
| 18 namespace { | |
| 19 | |
| 20 void SetGamepadButton(Gamepad* pad, | |
| 21 const vr::VRControllerState_t& controller_state, | |
| 22 uint64_t supported_buttons, | |
| 23 vr::EVRButtonId button_id) { | |
| 24 uint64_t button_mask = vr::ButtonMaskFromId(button_id); | |
| 25 if ((supported_buttons & button_mask) != 0) { | |
| 26 bool button_pressed = (controller_state.ulButtonPressed & button_mask) != 0; | |
| 27 bool button_touched = (controller_state.ulButtonTouched & button_mask) != 0; | |
| 28 pad->buttons[pad->buttons_length].touched = button_touched; | |
| 29 pad->buttons[pad->buttons_length].pressed = button_pressed; | |
| 30 pad->buttons[pad->buttons_length].value = button_pressed ? 1.0 : 0.0; | |
| 31 pad->buttons_length++; | |
| 32 } | |
| 33 } | |
| 34 | |
| 35 } // namespace | |
| 36 | |
| 37 OpenVRGamepadDataFetcher::Factory::Factory(unsigned int display_id) | |
| 38 : display_id_(display_id) { | |
| 39 DVLOG(1) << __FUNCTION__ << "=" << this; | |
| 40 } | |
| 41 | |
| 42 OpenVRGamepadDataFetcher::Factory::~Factory() { | |
| 43 DVLOG(1) << __FUNCTION__ << "=" << this; | |
| 44 } | |
| 45 | |
| 46 std::unique_ptr<GamepadDataFetcher> | |
| 47 OpenVRGamepadDataFetcher::Factory::CreateDataFetcher() { | |
| 48 return base::MakeUnique<OpenVRGamepadDataFetcher>(display_id_); | |
| 49 } | |
| 50 | |
| 51 GamepadSource OpenVRGamepadDataFetcher::Factory::source() { | |
| 52 return GAMEPAD_SOURCE_OPENVR; | |
| 53 } | |
| 54 | |
| 55 OpenVRGamepadDataFetcher::OpenVRGamepadDataFetcher(unsigned int display_id) | |
| 56 : display_id_(display_id), vr_system_(nullptr) { | |
| 57 DVLOG(1) << __FUNCTION__ << "=" << this; | |
| 58 } | |
| 59 | |
| 60 OpenVRGamepadDataFetcher::~OpenVRGamepadDataFetcher() { | |
| 61 DVLOG(1) << __FUNCTION__ << "=" << this; | |
| 62 } | |
| 63 | |
| 64 GamepadSource OpenVRGamepadDataFetcher::source() { | |
| 65 return GAMEPAD_SOURCE_OPENVR; | |
| 66 } | |
| 67 | |
| 68 void OpenVRGamepadDataFetcher::OnAddedToProvider() { | |
| 69 vr::EVRInitError init_error = vr::VRInitError_None; | |
| 70 vr_system_ = | |
| 71 vr::VR_Init(&init_error, vr::EVRApplicationType::VRApplication_Scene); | |
|
billorr
2017/04/19 17:27:37
Is vr_init safe to call multiple times? I can't f
| |
| 72 | |
| 73 if (init_error != vr::VRInitError_None) { | |
| 74 LOG(ERROR) << vr::VR_GetVRInitErrorAsEnglishDescription(init_error); | |
| 75 vr_system_ = nullptr; | |
| 76 return; | |
| 77 } | |
| 78 } | |
| 79 | |
| 80 void OpenVRGamepadDataFetcher::GetGamepadData(bool devices_changed_hint) { | |
| 81 if (!vr_system_) | |
| 82 return; | |
| 83 | |
| 84 vr::TrackedDevicePose_t tracked_devices_poses[vr::k_unMaxTrackedDeviceCount]; | |
| 85 vr_system_->GetDeviceToAbsoluteTrackingPose(vr::TrackingUniverseStanding, | |
| 86 0.0f, tracked_devices_poses, | |
| 87 vr::k_unMaxTrackedDeviceCount); | |
| 88 | |
| 89 for (uint32_t i = 0; i < vr::k_unMaxTrackedDeviceCount; ++i) { | |
| 90 if (vr_system_->GetTrackedDeviceClass(i) != | |
| 91 vr::TrackedDeviceClass_Controller) | |
| 92 continue; | |
| 93 | |
| 94 PadState* state = GetPadState(i); | |
| 95 if (!state) | |
| 96 continue; | |
| 97 | |
| 98 Gamepad& pad = state->data; | |
| 99 | |
| 100 vr::VRControllerState_t controller_state; | |
| 101 if (vr_system_->GetControllerState(i, &controller_state, | |
| 102 sizeof(controller_state))) { | |
| 103 pad.timestamp = controller_state.unPacketNum; | |
| 104 pad.connected = true; | |
| 105 | |
| 106 pad.pose.not_null = true; | |
| 107 | |
| 108 pad.pose.has_orientation = true; | |
| 109 pad.pose.has_position = true; | |
| 110 | |
| 111 vr::TrackedPropertyError error = vr::TrackedProp_Success; | |
| 112 char attached_device_id[vr::k_unMaxPropertyStringSize]; | |
| 113 vr_system_->GetStringTrackedDeviceProperty( | |
| 114 i, vr::Prop_AttachedDeviceId_String, attached_device_id, | |
| 115 vr::k_unMaxPropertyStringSize, &error); | |
| 116 | |
| 117 if (error == vr::TrackedProp_Success) { | |
| 118 swprintf(pad.id, Gamepad::kIdLengthCap, | |
| 119 base::UTF8ToUTF16(attached_device_id).c_str()); | |
| 120 } else { | |
| 121 swprintf(pad.id, Gamepad::kIdLengthCap, L"OpenVR Controller"); | |
| 122 } | |
| 123 swprintf(pad.mapping, Gamepad::kMappingLengthCap, L""); | |
| 124 | |
| 125 pad.display_id = display_id_; | |
| 126 | |
| 127 vr::ETrackedControllerRole hand = | |
| 128 vr_system_->GetControllerRoleForTrackedDeviceIndex(i); | |
| 129 | |
| 130 switch (hand) { | |
| 131 case vr::TrackedControllerRole_Invalid: | |
| 132 pad.hand = GamepadHand::kNone; | |
| 133 break; | |
| 134 case vr::TrackedControllerRole_LeftHand: | |
| 135 pad.hand = GamepadHand::kLeft; | |
| 136 break; | |
| 137 case vr::TrackedControllerRole_RightHand: | |
| 138 pad.hand = GamepadHand::kRight; | |
| 139 break; | |
| 140 } | |
| 141 | |
| 142 uint64_t supported_buttons = vr_system_->GetUint64TrackedDeviceProperty( | |
| 143 i, vr::Prop_SupportedButtons_Uint64); | |
| 144 | |
| 145 pad.buttons_length = 0; | |
| 146 pad.axes_length = 0; | |
| 147 | |
| 148 for (int j = 0; j < vr::k_unControllerStateAxisCount; ++j) { | |
| 149 int32_t axis_type = vr_system_->GetInt32TrackedDeviceProperty( | |
| 150 i, static_cast<vr::TrackedDeviceProperty>(vr::Prop_Axis0Type_Int32 + | |
| 151 j)); | |
| 152 switch (axis_type) { | |
| 153 case vr::k_eControllerAxis_Joystick: | |
| 154 case vr::k_eControllerAxis_TrackPad: | |
| 155 pad.axes[pad.axes_length++] = controller_state.rAxis[j].x; | |
| 156 pad.axes[pad.axes_length++] = controller_state.rAxis[j].y; | |
| 157 | |
| 158 SetGamepadButton( | |
| 159 &pad, controller_state, supported_buttons, | |
| 160 static_cast<vr::EVRButtonId>(vr::k_EButton_Axis0 + j)); | |
| 161 | |
| 162 break; | |
| 163 case vr::k_eControllerAxis_Trigger: | |
| 164 pad.buttons[pad.buttons_length].value = controller_state.rAxis[j].x; | |
| 165 | |
| 166 uint64_t button_mask = vr::ButtonMaskFromId( | |
| 167 static_cast<vr::EVRButtonId>(vr::k_EButton_Axis0 + j)); | |
| 168 if ((supported_buttons & button_mask) != 0) { | |
| 169 pad.buttons[pad.buttons_length].pressed = | |
| 170 (controller_state.ulButtonPressed & button_mask) != 0; | |
| 171 } | |
| 172 | |
| 173 pad.buttons_length++; | |
| 174 break; | |
| 175 } | |
| 176 } | |
| 177 | |
| 178 SetGamepadButton(&pad, controller_state, supported_buttons, | |
| 179 vr::k_EButton_A); | |
| 180 SetGamepadButton(&pad, controller_state, supported_buttons, | |
| 181 vr::k_EButton_Grip); | |
| 182 SetGamepadButton(&pad, controller_state, supported_buttons, | |
| 183 vr::k_EButton_ApplicationMenu); | |
| 184 SetGamepadButton(&pad, controller_state, supported_buttons, | |
| 185 vr::k_EButton_DPad_Left); | |
| 186 SetGamepadButton(&pad, controller_state, supported_buttons, | |
| 187 vr::k_EButton_DPad_Up); | |
| 188 SetGamepadButton(&pad, controller_state, supported_buttons, | |
| 189 vr::k_EButton_DPad_Right); | |
| 190 SetGamepadButton(&pad, controller_state, supported_buttons, | |
| 191 vr::k_EButton_DPad_Down); | |
| 192 } | |
| 193 | |
| 194 const vr::TrackedDevicePose_t& pose = tracked_devices_poses[i]; | |
| 195 if (pose.bPoseIsValid) { | |
| 196 const vr::HmdMatrix34_t& mat = pose.mDeviceToAbsoluteTracking; | |
| 197 gfx::Transform transform( | |
| 198 mat.m[0][0], mat.m[0][1], mat.m[0][2], mat.m[0][3], mat.m[1][0], | |
| 199 mat.m[1][1], mat.m[1][2], mat.m[1][3], mat.m[2][0], mat.m[2][1], | |
| 200 mat.m[2][2], mat.m[2][3], 0, 0, 0, 1); | |
| 201 | |
| 202 gfx::DecomposedTransform decomposed_transform; | |
| 203 gfx::DecomposeTransform(&decomposed_transform, transform); | |
| 204 | |
| 205 pad.pose.orientation.not_null = true; | |
| 206 pad.pose.orientation.x = decomposed_transform.quaternion[0]; | |
| 207 pad.pose.orientation.y = decomposed_transform.quaternion[1]; | |
| 208 pad.pose.orientation.z = decomposed_transform.quaternion[2]; | |
| 209 pad.pose.orientation.w = decomposed_transform.quaternion[3]; | |
| 210 | |
| 211 pad.pose.position.not_null = true; | |
| 212 pad.pose.position.x = decomposed_transform.translate[0]; | |
| 213 pad.pose.position.y = decomposed_transform.translate[1]; | |
| 214 pad.pose.position.z = decomposed_transform.translate[2]; | |
| 215 | |
| 216 pad.pose.angular_velocity.not_null = true; | |
| 217 pad.pose.angular_velocity.x = pose.vAngularVelocity.v[0]; | |
| 218 pad.pose.angular_velocity.y = pose.vAngularVelocity.v[1]; | |
| 219 pad.pose.angular_velocity.z = pose.vAngularVelocity.v[2]; | |
| 220 | |
| 221 pad.pose.linear_velocity.not_null = true; | |
| 222 pad.pose.linear_velocity.x = pose.vVelocity.v[0]; | |
| 223 pad.pose.linear_velocity.y = pose.vVelocity.v[1]; | |
| 224 pad.pose.linear_velocity.z = pose.vVelocity.v[2]; | |
| 225 } else { | |
| 226 pad.pose.orientation.not_null = false; | |
| 227 pad.pose.position.not_null = false; | |
| 228 pad.pose.angular_velocity.not_null = false; | |
| 229 pad.pose.linear_velocity.not_null = false; | |
| 230 } | |
| 231 } | |
| 232 } | |
| 233 | |
| 234 void OpenVRGamepadDataFetcher::PauseHint(bool paused) {} | |
| 235 | |
| 236 } // namespace device | |
| OLD | NEW |