14#include <private/qquick3djoint_p.h>
28 delete m_handInputState[Hand::LeftHand];
29 delete m_handInputState[Hand::RightHand];
31 m_handInputState[Hand::LeftHand] =
nullptr;
32 m_handInputState[Hand::RightHand] =
nullptr;
35QQuick3DXrInputManagerPrivate::QXRHandComponentPath QQuick3DXrInputManagerPrivate::makeHandInputPaths(
const QByteArrayView path)
37 QXRHandComponentPath
res;
38 setPath(
res.paths[Hand::LeftHand],
"/user/hand/left/" +
path);
39 setPath(
res.paths[Hand::RightHand],
"/user/hand/right/" +
path);
47 setPath(
res,
path.toByteArray());
51QQuick3DGeometry *QQuick3DXrInputManagerPrivate::createHandMeshGeometry(
const HandMeshData &handMeshData)
57 const qsizetype expectedLength = handMeshData.vertexPositions.size();
58 bool hasPositions = !handMeshData.vertexPositions.isEmpty();
59 bool hasNormals = handMeshData.vertexNormals.size() >= expectedLength;
60 bool hasUV0s = handMeshData.vertexUVs.size() >= expectedLength;
61 bool hasJoints = handMeshData.vertexBlendIndices.size() >= expectedLength;
62 bool hasWeights = handMeshData.vertexBlendWeights.size() >= expectedLength;
63 bool hasIndexes = !handMeshData.indices.isEmpty();
68 offset += 3 *
sizeof(float);
73 offset += 3 *
sizeof(float);
78 offset += 2 *
sizeof(float);
88 offset += 4 *
sizeof(float);
100 vertexBuffer.
reserve(bufferSize);
105 auto appendFloat = [&vertexBuffer](
float f) {
106 vertexBuffer.
append(
reinterpret_cast<const char *
>(&
f),
sizeof(float));
108 auto appendInt = [&vertexBuffer](
qint32 i) {
109 vertexBuffer.
append(
reinterpret_cast<const char *
>(&
i),
sizeof(
qint32));
127 const auto &normal = handMeshData.vertexNormals[
i];
128 appendFloat(normal.x);
129 appendFloat(normal.y);
130 appendFloat(normal.z);
134 const auto &uv0 = handMeshData.vertexUVs[
i];
140 const auto &joint = handMeshData.vertexBlendIndices[
i];
148 const auto &
weight = handMeshData.vertexBlendWeights[
i];
156 geometry->
setBounds(minBounds, maxBounds);
161 const qsizetype indexLength = handMeshData.indices.size();
163 indexBuffer.
reserve(indexLength *
sizeof(int16_t));
165 const auto &
index = handMeshData.indices[
i];
166 indexBuffer.
append(
reinterpret_cast<const char *
>(&
index),
sizeof(int16_t));
177 qWarning() <<
"QQuick3DXrInputManager: Trying to initialize an already initialized session";
181 m_instance = instance;
188 QXRHandComponentPath aClick = makeHandInputPaths(
"input/a/click");
189 QXRHandComponentPath bClick = makeHandInputPaths(
"input/b/click");
190 QXRHandComponentPath aTouch = makeHandInputPaths(
"input/a/touch");
191 QXRHandComponentPath bTouch = makeHandInputPaths(
"input/b/touch");
193 QXRHandComponentPath xClick = makeHandInputPaths(
"input/x/click");
194 QXRHandComponentPath yClick = makeHandInputPaths(
"input/y/click");
195 QXRHandComponentPath xTouch = makeHandInputPaths(
"input/x/touch");
196 QXRHandComponentPath yTouch = makeHandInputPaths(
"input/y/touch");
198 QXRHandComponentPath menuClick = makeHandInputPaths(
"input/menu/click");
199 QXRHandComponentPath systemClick = makeHandInputPaths(
"input/system/click");
200 QXRHandComponentPath systemTouch = makeHandInputPaths(
"input/system/touch");
202 QXRHandComponentPath squeezeValue = makeHandInputPaths(
"input/squeeze/value");
203 QXRHandComponentPath squeezeForce = makeHandInputPaths(
"input/squeeze/force");
204 QXRHandComponentPath squeezeClick = makeHandInputPaths(
"input/squeeze/click");
206 QXRHandComponentPath triggerValue = makeHandInputPaths(
"input/trigger/value");
207 QXRHandComponentPath triggerTouch = makeHandInputPaths(
"input/trigger/touch");
208 QXRHandComponentPath triggerClick = makeHandInputPaths(
"input/trigger/click");
210 QXRHandComponentPath thumbstickX = makeHandInputPaths(
"input/thumbstick/x");
211 QXRHandComponentPath thumbstickY = makeHandInputPaths(
"input/thumbstick/y");
212 QXRHandComponentPath thumbstickClick = makeHandInputPaths(
"input/thumbstick/click");
213 QXRHandComponentPath thumbstickTouch = makeHandInputPaths(
"input/thumbstick/touch");
214 QXRHandComponentPath thumbrestTouch = makeHandInputPaths(
"input/thumbrest/touch");
216 QXRHandComponentPath trackpadX = makeHandInputPaths(
"input/trackpad/x");
217 QXRHandComponentPath trackpadY = makeHandInputPaths(
"input/trackpad/y");
218 QXRHandComponentPath trackpadForce = makeHandInputPaths(
"input/trackpad/force");
219 QXRHandComponentPath trackpadClick = makeHandInputPaths(
"input/trackpad/click");
220 QXRHandComponentPath trackpadTouch = makeHandInputPaths(
"input/trackpad/touch");
222 XrPath handLeftGripPose;
223 XrPath handLeftAimPose;
224 XrPath handLeftHaptic;
226 XrPath handRightGripPose;
227 XrPath handRightAimPose;
228 XrPath handRightHaptic;
232 setPath(handLeftGripPose,
"/user/hand/left/input/grip/pose");
233 setPath(handLeftAimPose,
"/user/hand/left/input/aim/pose");
234 setPath(handLeftHaptic,
"/user/hand/left/output/haptic");
236 setPath(handRightGripPose,
"/user/hand/right/input/grip/pose");
237 setPath(handRightAimPose,
"/user/hand/right/input/aim/pose");
238 setPath(handRightHaptic,
"/user/hand/right/output/haptic");
242 using XrActionBindings = std::vector<XrActionSuggestedBinding>;
243 using HandInputMapping = std::vector<std::tuple<QQuick3DXrInputAction::Action, QXRHandComponentPath, SubPathSelector>>;
244 auto addToBindings = [
this](XrActionBindings &bindings,
const HandInputMapping &defs){
247 bindings.push_back({ m_inputActions[actionId],
path.paths[Hand::LeftHand] });
249 bindings.push_back({ m_inputActions[actionId],
path.paths[Hand::RightHand] });
255 HandInputMapping mappingDefs {
276 XrPath oculusTouchProfile;
277 setPath(oculusTouchProfile,
"/interaction_profiles/oculus/touch_controller");
278 std::vector<XrActionSuggestedBinding> bindings {{
279 {m_handActions.gripPoseAction, handLeftGripPose},
280 {m_handActions.aimPoseAction, handLeftAimPose},
281 {m_handActions.hapticAction, handLeftHaptic},
283 {m_handActions.gripPoseAction, handRightGripPose},
284 {m_handActions.aimPoseAction, handRightAimPose},
285 {m_handActions.hapticAction, handRightHaptic},
288 addToBindings(bindings, mappingDefs);
290 XrInteractionProfileSuggestedBinding suggestedBindings{};
291 suggestedBindings.type = XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING;
292 suggestedBindings.interactionProfile = oculusTouchProfile;
293 suggestedBindings.suggestedBindings = bindings.data();
294 suggestedBindings.countSuggestedBindings = (uint32_t)bindings.size();
295 if (!checkXrResult(xrSuggestInteractionProfileBindings(m_instance, &suggestedBindings)))
296 qWarning(
"Failed to get suggested interaction profile bindings for Oculus touch");
302 XrPath handInteractionProfile;
303 setPath(handInteractionProfile,
"/interaction_profiles/microsoft/hand_interaction");
304 std::vector<XrActionSuggestedBinding> bindings {{
305 {m_handActions.gripPoseAction, handLeftGripPose},
306 {m_handActions.aimPoseAction, handLeftAimPose},
307 {m_handActions.gripPoseAction, handRightGripPose},
308 {m_handActions.aimPoseAction, handRightAimPose},
311 HandInputMapping mappingDefs {
315 addToBindings(bindings, mappingDefs);
317 XrInteractionProfileSuggestedBinding suggestedBindings{};
318 suggestedBindings.type = XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING;
319 suggestedBindings.interactionProfile = handInteractionProfile;
320 suggestedBindings.suggestedBindings = bindings.data();
321 suggestedBindings.countSuggestedBindings = (uint32_t)bindings.size();
323 if (!checkXrResult(xrSuggestInteractionProfileBindings(m_instance, &suggestedBindings)))
324 qWarning(
"Failed to get suggested interaction profile bindings for MSFT hand interaction");
328 XrPath htcViveProfile;
329 setPath(htcViveProfile,
"/interaction_profiles/htc/vive_controller");
331 HandInputMapping mappingDefs {
343 std::vector<XrActionSuggestedBinding> bindings {{
344 {m_handActions.gripPoseAction, handLeftGripPose},
345 {m_handActions.aimPoseAction, handLeftAimPose},
346 {m_handActions.hapticAction, handLeftHaptic},
348 {m_handActions.gripPoseAction, handRightGripPose},
349 {m_handActions.aimPoseAction, handRightAimPose},
350 {m_handActions.hapticAction, handRightHaptic},
353 addToBindings(bindings, mappingDefs);
355 XrInteractionProfileSuggestedBinding suggestedBindings{};
356 suggestedBindings.type = XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING;
357 suggestedBindings.interactionProfile = htcViveProfile;
358 suggestedBindings.suggestedBindings = bindings.data();
359 suggestedBindings.countSuggestedBindings = (uint32_t)bindings.size();
360 if (!checkXrResult(xrSuggestInteractionProfileBindings(m_instance, &suggestedBindings)))
361 qWarning(
"Failed to get suggested interaction profile bindings for Vive controller");
366 XrPath microsoftMotionProfile;
367 setPath(microsoftMotionProfile,
"/interaction_profiles/microsoft/motion_controller");
372 XrPath valveIndexProfile;
373 setPath(valveIndexProfile,
"/interaction_profiles/valve/index_controller");
378 XrActionSpaceCreateInfo actionSpaceInfo{};
379 actionSpaceInfo.type = XR_TYPE_ACTION_SPACE_CREATE_INFO;
380 actionSpaceInfo.action = m_handActions.gripPoseAction;
381 actionSpaceInfo.poseInActionSpace.orientation.w = 1.0f;
383 actionSpaceInfo.subactionPath = m_handSubactionPath[0];
384 if (!checkXrResult(xrCreateActionSpace(m_session, &actionSpaceInfo, &m_handGripSpace[0])))
385 qWarning(
"Failed to create action space for handGripSpace[0]");
386 actionSpaceInfo.subactionPath = m_handSubactionPath[1];
387 if (!checkXrResult(xrCreateActionSpace(m_session, &actionSpaceInfo, &m_handGripSpace[1])))
388 qWarning(
"Failed to create action space for handGripSpace[1]");
390 actionSpaceInfo.action = m_handActions.aimPoseAction;
391 actionSpaceInfo.subactionPath = m_handSubactionPath[0];
392 if (!checkXrResult(xrCreateActionSpace(m_session, &actionSpaceInfo, &m_handAimSpace[0])))
393 qWarning(
"Failed to create action space for handAimSpace[0]");
394 actionSpaceInfo.subactionPath = m_handSubactionPath[1];
395 if (!checkXrResult(xrCreateActionSpace(m_session, &actionSpaceInfo, &m_handAimSpace[1])))
396 qWarning(
"Failed to create action space for handAimSpace[1]");
400 XrSessionActionSetsAttachInfo attachInfo{};
401 attachInfo.type = XR_TYPE_SESSION_ACTION_SETS_ATTACH_INFO;
402 attachInfo.countActionSets = 1;
403 attachInfo.actionSets = &m_actionSet;
404 if (!checkXrResult(xrAttachSessionActionSets(m_session, &attachInfo)))
405 qWarning(
"Failed to attach action sets to session");
407 m_initialized =
true;
415 m_initialized =
false;
417 xrDestroySpace(m_handGripSpace[0]);
418 xrDestroySpace(m_handGripSpace[1]);
419 xrDestroySpace(m_handAimSpace[0]);
420 xrDestroySpace(m_handAimSpace[1]);
429 m_instance = {XR_NULL_HANDLE};
430 m_session = {XR_NULL_HANDLE};
435 QSSG_ASSERT(inputManager !=
nullptr,
return nullptr);
436 return inputManager->d_func();
445 const XrActiveActionSet activeActionSet{m_actionSet, XR_NULL_PATH};
446 XrActionsSyncInfo syncInfo{};
447 syncInfo.type = XR_TYPE_ACTIONS_SYNC_INFO;
448 syncInfo.countActiveActionSets = 1;
449 syncInfo.activeActionSets = &activeActionSet;
450 XrResult
result = xrSyncActions(m_session, &syncInfo);
451 if (!(
result == XR_SUCCESS ||
452 result == XR_SESSION_LOSS_PENDING ||
453 result == XR_SESSION_NOT_FOCUSED))
455 if (!checkXrResult(
result)) {
462 XrActionStateGetInfo getInfo{};
463 getInfo.type = XR_TYPE_ACTION_STATE_GET_INFO;
464 for (
int i = 0;
i < 2; ++
i) {
466 getInfo.subactionPath = m_handSubactionPath[
i];
467 auto &inputState = m_handInputState[
i];
469 for (
const auto &def : m_handInputActionDefs) {
470 getInfo.action = m_inputActions[def.id];
472 case XR_ACTION_TYPE_BOOLEAN_INPUT: {
473 XrActionStateBoolean boolValue{};
474 boolValue.type = XR_TYPE_ACTION_STATE_BOOLEAN;
475 if (checkXrResult(xrGetActionStateBoolean(m_session, &getInfo, &boolValue))) {
476 if (boolValue.isActive && boolValue.changedSinceLastSync) {
478 m_handInputState[
i]->
setInputValue(def.id, def.shortName,
float(boolValue.currentState));
481 qWarning(
"Failed to get action state for bool hand input");
485 case XR_ACTION_TYPE_FLOAT_INPUT: {
486 XrActionStateFloat floatValue{};
487 floatValue.type = XR_TYPE_ACTION_STATE_FLOAT;
488 if (checkXrResult(xrGetActionStateFloat(m_session, &getInfo, &floatValue))) {
489 if (floatValue.isActive && floatValue.changedSinceLastSync) {
491 m_handInputState[
i]->
setInputValue(def.id, def.shortName,
float(floatValue.currentState));
494 qWarning(
"Failed to get action state for float hand input");
498 case XR_ACTION_TYPE_VECTOR2F_INPUT:
499 case XR_ACTION_TYPE_POSE_INPUT:
500 case XR_ACTION_TYPE_VIBRATION_OUTPUT:
501 case XR_ACTION_TYPE_MAX_ENUM:
507 getInfo.action = m_handActions.gripPoseAction;
508 XrActionStatePose poseState{};
509 poseState.type = XR_TYPE_ACTION_STATE_POSE;
510 if (checkXrResult(xrGetActionStatePose(m_session, &getInfo, &poseState)))
511 inputState->setIsActive(poseState.isActive);
513 qWarning(
"Failed to get action state pose");
528 for (
auto hand : {Hand::LeftHand, Hand::RightHand}) {
529 XrSpaceLocation spaceLocation{};
530 spaceLocation.type = XR_TYPE_SPACE_LOCATION;
532 res = xrLocateSpace(
handSpace(hand), appSpace, predictedDisplayTime, &spaceLocation);
537 && XR_UNQUALIFIED_SUCCESS(
res) && (spaceLocation.locationFlags & XR_SPACE_LOCATION_POSITION_VALID_BIT)
538 && (spaceLocation.locationFlags & XR_SPACE_LOCATION_ORIENTATION_VALID_BIT);
540 if (XR_UNQUALIFIED_SUCCESS(
res)) {
541 if ((spaceLocation.locationFlags & XR_SPACE_LOCATION_POSITION_VALID_BIT) != 0 &&
542 (spaceLocation.locationFlags & XR_SPACE_LOCATION_ORIENTATION_VALID_BIT) != 0) {
546 spaceLocation.pose.position.y,
547 spaceLocation.pose.position.z) * 100.0f);
549 spaceLocation.pose.orientation.x,
550 spaceLocation.pose.orientation.y,
551 spaceLocation.pose.orientation.z));
557 const char* handName[] = {
"left",
"right"};
558 qDebug(
"Unable to locate %s hand action space in app space: %d", handName[hand],
res);
568 XrHandTrackingAimStateFB aimState[2] = {{}, {}};
569 XrHandJointVelocitiesEXT velocities[2]{{}, {}};
570 XrHandJointLocationsEXT
locations[2]{{}, {}};
571 XrHandJointsLocateInfoEXT locateInfo[2] = {{}, {}};
573 for (
auto hand : {Hand::LeftHand, Hand::RightHand}) {
577 aimState[hand].type = XR_TYPE_HAND_TRACKING_AIM_STATE_FB;
579 velocities[hand].type = XR_TYPE_HAND_JOINT_VELOCITIES_EXT;
580 velocities[hand].jointCount = XR_HAND_JOINT_COUNT_EXT;
582 velocities[hand].next = aimExtensionEnabled ? &aimState[hand] :
nullptr;
584 locations[hand].type = XR_TYPE_HAND_JOINT_LOCATIONS_EXT;
585 locations[hand].next = &velocities[hand];
586 locations[hand].jointCount = XR_HAND_JOINT_COUNT_EXT;
589 locateInfo[hand].type = XR_TYPE_HAND_JOINTS_LOCATE_INFO_EXT;
590 locateInfo[hand].baseSpace = appSpace;
591 locateInfo[hand].time = predictedDisplayTime;
593 qWarning(
"Failed to locate hand joints for hand tracker");
596 jp.reserve(XR_HAND_JOINT_COUNT_EXT);
597 QList<QQuaternion> jr;
598 jr.reserve(XR_HAND_JOINT_COUNT_EXT);
608 if (aimExtensionEnabled) {
610 for (
auto hand : {Hand::LeftHand, Hand::RightHand}) {
611 const uint state = aimState[hand].status;
612 const uint oldState = m_aimStateFlags[hand];
614 if ((
state & flag) != (oldState & flag))
623 m_aimStateFlags[hand] =
state;
627 for (
auto hand : {Hand::LeftHand, Hand::RightHand}) {
628 if (!m_validAimStateFromUpdatePoses[hand]) {
631 aimState[hand].aimPose.position.y,
632 aimState[hand].aimPose.position.z) * 100.0f);
634 aimState[hand].aimPose.orientation.x,
635 aimState[hand].aimPose.orientation.y,
636 aimState[hand].aimPose.orientation.z));
645void QQuick3DXrInputManagerPrivate::setupHandTracking()
648 "xrCreateHandTrackerEXT",
651 "xrDestroyHandTrackerEXT",
654 "xrLocateHandJointsEXT",
661 XrHandTrackerCreateInfoEXT createInfo{};
662 createInfo.type = XR_TYPE_HAND_TRACKER_CREATE_INFO_EXT;
663 createInfo.handJointSet = XR_HAND_JOINT_SET_DEFAULT_EXT;
664 createInfo.hand = XR_HAND_LEFT_EXT;
666 qWarning(
"Failed to create left hand tracker");
667 createInfo.hand = XR_HAND_RIGHT_EXT;
669 qWarning(
"Failed to create right hand tracker");
672 for (
auto hand : {Hand::LeftHand, Hand::RightHand}) {
673 if (queryHandMesh(hand))
674 createHandModelData(hand);
679bool QQuick3DXrInputManagerPrivate::queryHandMesh(Hand hand)
681 XrHandTrackingMeshFB mesh {};
682 mesh.type = XR_TYPE_HAND_TRACKING_MESH_FB;
685 qWarning(
"Failed to query hand mesh info.");
689 mesh.jointCapacityInput = mesh.jointCountOutput;
690 mesh.vertexCapacityInput = mesh.vertexCountOutput;
691 mesh.indexCapacityInput = mesh.indexCountOutput;
692 m_handMeshData[hand].vertexPositions.resize(mesh.vertexCapacityInput);
693 m_handMeshData[hand].vertexNormals.resize(mesh.vertexCapacityInput);
694 m_handMeshData[hand].vertexUVs.resize(mesh.vertexCapacityInput);
695 m_handMeshData[hand].vertexBlendIndices.resize(mesh.vertexCapacityInput);
696 m_handMeshData[hand].vertexBlendWeights.resize(mesh.vertexCapacityInput);
697 m_handMeshData[hand].indices.resize(mesh.indexCapacityInput);
698 mesh.jointBindPoses = m_handMeshData[hand].jointBindPoses;
699 mesh.jointParents = m_handMeshData[hand].jointParents;
700 mesh.jointRadii = m_handMeshData[hand].jointRadii;
701 mesh.vertexPositions = m_handMeshData[hand].vertexPositions.data();
702 mesh.vertexNormals = m_handMeshData[hand].vertexNormals.data();
703 mesh.vertexUVs = m_handMeshData[hand].vertexUVs.data();
704 mesh.vertexBlendIndices = m_handMeshData[hand].vertexBlendIndices.data();
705 mesh.vertexBlendWeights = m_handMeshData[hand].vertexBlendWeights.data();
706 mesh.indices = m_handMeshData[hand].indices.data();
709 qWarning(
"Failed to get hand mesh data.");
716void QQuick3DXrInputManagerPrivate::setupActions()
718 m_handInputActionDefs = {
747 XrActionSetCreateInfo actionSetInfo{};
748 actionSetInfo.type = XR_TYPE_ACTION_SET_CREATE_INFO;
749 strcpy(actionSetInfo.actionSetName,
"gameplay");
750 strcpy(actionSetInfo.localizedActionSetName,
"Gameplay");
751 actionSetInfo.priority = 0;
752 if (!checkXrResult(xrCreateActionSet(m_instance, &actionSetInfo, &m_actionSet)))
753 qWarning(
"Failed to create gameplay action set");
757 setPath(m_handSubactionPath[0],
"/user/hand/left");
758 setPath(m_handSubactionPath[1],
"/user/hand/right");
760 for (
const auto &def : m_handInputActionDefs) {
761 createAction(def.type,
766 m_inputActions[def.id]);
769 createAction(XR_ACTION_TYPE_VIBRATION_OUTPUT,
774 m_handActions.hapticAction);
775 createAction(XR_ACTION_TYPE_POSE_INPUT,
780 m_handActions.gripPoseAction);
781 createAction(XR_ACTION_TYPE_POSE_INPUT,
786 m_handActions.aimPoseAction);
790void QQuick3DXrInputManagerPrivate::destroyActions()
792 for (
auto &action : m_inputActions) {
794 xrDestroyAction(action);
797 xrDestroyAction(m_handActions.gripPoseAction);
798 xrDestroyAction(m_handActions.aimPoseAction);
799 xrDestroyAction(m_handActions.hapticAction);
801 xrDestroyActionSet(m_actionSet);
804bool QQuick3DXrInputManagerPrivate::checkXrResult(
const XrResult &
result)
809bool QQuick3DXrInputManagerPrivate::resolveXrFunction(
const char *
name, PFN_xrVoidFunction *function)
811 XrResult
result = xrGetInstanceProcAddr(m_instance,
name, function);
822 if (!checkXrResult(xrStringToPath(m_instance,
pathString.constData(), &
path)))
826void QQuick3DXrInputManagerPrivate::createAction(XrActionType
type,
828 const char *localizedName,
830 XrPath *subactionPath,
833 XrActionCreateInfo actionInfo{};
834 actionInfo.type = XR_TYPE_ACTION_CREATE_INFO;
835 actionInfo.actionType =
type;
836 strcpy(actionInfo.actionName,
name);
837 strcpy(actionInfo.localizedActionName, localizedName);
838 actionInfo.countSubactionPaths =
quint32(numSubactions);
839 actionInfo.subactionPaths = subactionPath;
840 if (!checkXrResult(xrCreateAction(m_actionSet, &actionInfo, &action)))
841 qDebug() <<
"xrCreateAction failed. Name:" <<
name <<
"localizedName:" << localizedName;
844void QQuick3DXrInputManagerPrivate::getBoolInputState(XrActionStateGetInfo &getInfo,
const XrAction &action, std::function<
void(
bool)> setter)
846 getInfo.action = action;
848 boolValue.type = XR_TYPE_ACTION_STATE_BOOLEAN;
849 if (checkXrResult(xrGetActionStateBoolean(m_session, &getInfo, &boolValue))) {
853 qWarning(
"Failed to get action state: bool");
857void QQuick3DXrInputManagerPrivate::getFloatInputState(XrActionStateGetInfo &getInfo,
const XrAction &action, std::function<
void(
float)> setter)
859 getInfo.action = action;
860 XrActionStateFloat floatValue{};
861 floatValue.type = XR_TYPE_ACTION_STATE_FLOAT;
862 if (checkXrResult(xrGetActionStateFloat(m_session, &getInfo, &floatValue))) {
863 if (floatValue.isActive == XR_TRUE)
864 setter(
float(floatValue.currentState));
866 qWarning(
"Failed to get action state: float");
873 return m_handGripSpace[hand];
875 return m_handAimSpace[hand];
880 return m_handInputState[hand]->
isActive();
900 return m_handInputState[Hand::LeftHand];
905 return m_handInputState[Hand::RightHand];
925 model->setGeometry(geometry);
928 auto jointListProp = skin->
joints();
929 QList<QMatrix4x4> inverseBindPoses;
930 inverseBindPoses.reserve(XR_HAND_JOINT_COUNT_EXT);
932 const auto &handMeshData = m_handMeshData[hand];
934 for (
int i = 0;
i < XR_HAND_JOINT_COUNT_EXT; ++
i) {
935 const auto &pose = handMeshData.jointBindPoses[
i];
940 joint->setPosition(
pos);
941 joint->setRotation(rot);
942 jointListProp.append(&jointListProp, joint);
945 model->setSkin(skin);
952 if (
model->geometry() !=
nullptr ||
model->skin() !=
nullptr) {
953 qWarning() <<
"Hand model already has geometry or skin set.";
957 auto hand =
model->hand();
959 setupHandModelInternal(
model, Hand::LeftHand);
961 setupHandModelInternal(
model, Hand::RightHand);
963 qWarning() <<
"No matching hand tracker input found for hand model.";
966void QQuick3DXrInputManagerPrivate::createHandModelData(Hand hand)
968 const auto &handMeshData = m_handMeshData[hand];
970 auto &geometry = m_handGeometryData[hand].geometry;
972 geometry = createHandMeshGeometry(handMeshData);
void reserve(qsizetype size)
Attempts to allocate memory for at least size bytes.
QByteArray & append(char c)
This is an overloaded member function, provided for convenience. It differs from the above function o...
The QMatrix4x4 class represents a 4x4 transformation matrix in 3D space.
The QQuaternion class represents a quaternion consisting of a vector and scalar.
\qmltype Geometry \inherits Object3D \inqmlmodule QtQuick3D \instantiates QQuick3DGeometry
void setPrimitiveType(PrimitiveType type)
Sets the primitive type used for rendering to type.
void setStride(int stride)
Sets the stride of the vertex buffer to stride, measured in bytes.
void addAttribute(Attribute::Semantic semantic, int offset, Attribute::ComponentType componentType)
Adds vertex attribute description.
void setVertexData(const QByteArray &data)
Sets the vertex buffer data.
void setBounds(const QVector3D &min, const QVector3D &max)
Sets the bounding volume of the geometry to the cube defined by the points min and max.
void setIndexData(const QByteArray &data)
Sets the index buffer to data.
void setInverseBindPoses(const QList< QMatrix4x4 > &poses)
QQmlListProperty< QQuick3DNode > joints
\qmlproperty List<QtQuick3D::Node> Skin::joints
The QVector3D class represents a vector or vertex in 3D space.
QQuaternion toQQuaternion(const XrQuaternionf &q)
bool checkXrResult(XrResult result, XrInstance instance)
QVector3D toQVector(const XrVector3f &v)
Combined button and popup list for selecting options.
void setter(QUntypedPropertyData *d, const void *value)
QString boolValue(bool v)
QT_BEGIN_NAMESPACE constexpr const T & qMin(const T &a, const T &b)
constexpr const T & qMax(const T &a, const T &b)
GLuint GLuint GLfloat weight
GLenum GLsizei const void * pathString
const void GLsizei GLsizei stride
GLenum GLuint GLintptr offset
GLuint GLenum GLenum transform
GLsizei const GLchar *const * path
GLuint const GLint * locations
static qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
#define QSSG_ASSERT(cond, action)
QSqlQueryModel * model
[16]
QFileSelector selector
[1]
QNetworkAccessManager manager