Sur cette page

Qt Quick 3D - XR Exemple de saisie simple

Démonstration de l'entrée de contrôleur dans Qt Quick 3D XR.

Théière avec rayon de contrôle XR pointant vers un panneau d'interface utilisateur avec des boutons de couleur

Cet exemple montre comment utiliser les API d'entrée de bas niveau dans Qt Quick 3D XR pour interagir avec des objets 2D et 3D dans la scène. Il suit la structure de base de l'exemple xr_simple.

Entrée du contrôleur

Dans cet exemple, nous faisons ray picking à partir de la position de XrController:

XrController {
    id: rightController
    controller: XrController.RightController
    poseSpace: XrController.AimPose

    property QtObject hitObject

    onRotationChanged: {
        const pickResult = xrView.rayPick(scenePosition, forward)
        if (pickResult.hitType !== PickResult.Null) {
            pickRay.hit = true
            pickRay.length = pickResult.distance
            hitObject = pickResult.objectHit
            cursorSphere.position = pickResult.scenePosition
            cursorSphere.visible = true
        } else {
            pickRay.hit = false
            pickRay.length = 50
            hitObject = null
            cursorSphere.visible = false
        }
    }

    Node {
        id: pickRay
        property real length: 50
        property bool hit: false

        Model {
            eulerRotation.x: -90
            scale: Qt.vector3d(0.005, pickRay.length/100, 0.005)
            source: "#Cone"
            materials: PrincipledMaterial {
                baseColor: rightTrigger.pressed ? "#99aaff" : "#cccccc"
                lighting: PrincipledMaterial.NoLighting
            }
            opacity: 0.8
        }
    }

    Node {
        z: 5
        Model {
            eulerRotation.x: 90
            scale: Qt.vector3d(0.05, 0.10, 0.05)
            source: "#Cylinder"
            materials: PrincipledMaterial {
                baseColor: "black"
                roughness: 0.2
            }
        }
    }
}

Celui-ci exécute les fonctions suivantes :

  • Si nous touchons quelque chose, nous modifions la longueur du pickRay pour qu'il touche la chose que nous avons touchée. Le pickRay est un cône semi-transparent (un cylindre effilé) qui montre où l'utilisateur vise. Nous déplaçons également cursorSphere à l'endroit où le rayon touche. (cursorSphere est une sphère semi-transparente qui est un enfant de XrView).
  • Nous attribuons la propriété hitObject à l'objet que nous avons touché.

Nous utilisons également un cylindre noir comme représentation générique du contrôleur.

Pour cet exemple, nous avons créé un simple bouton-poussoir en 3D dans le fichier ExampleButton.qml. (Les détails du fonctionnement du bouton ne sont pas expliqués ici.) Nous créons une action XrInputAction pour réagir aux pressions de la gâchette :

XrInputAction {
    id: rightTrigger
    controller: XrInputAction.RightController
    actionId: [XrInputAction.TriggerPressed, XrInputAction.TriggerValue, XrInputAction.IndexFingerPinch]
    onTriggered: {
        const button = rightController.hitObject as ExampleButton
        if (button && button !== panel.activeButton) {
            panel.activeButton = button
        }
    }
}

L'action rightTrigger réagit à plusieurs identifiants différents afin de prendre en charge à la fois le suivi de la main et différents types de contrôleurs. Lorsque l'action est déclenchée, elle vérifie si le hitObject que nous avons défini ci-dessus est du type ExampleButton. Si tel est le cas, le bouton est activé.

Pour permettre à un contrôleur 3D d'interagir avec un contenu 2D, nous devons ajouter un XrVirtualMouse pour établir une correspondance entre les deux :

XrInputAction {
    id: rightThumbstickX
    controller: XrInputAction.RightController
    actionId: [XrInputAction.ThumbstickX]
}
XrInputAction {
    id: rightThumbstickY
    controller: XrInputAction.RightController
    actionId: [XrInputAction.ThumbstickY]
}

XrVirtualMouse {
    view: xrView
    source: rightController
    leftMouseButton: rightTrigger.pressed
    scrollWheelX: rightThumbstickX.value
    scrollWheelY: rightThumbstickY.value
}

Tout d'abord, nous ajoutons deux actions supplémentaires pour détecter la position horizontale et verticale du pouce. Ensuite, nous créons une action XrVirtualMouse, en utilisant l'action XrController comme source de position. Nous utilisons l'action rightTrigger que nous avons créée plus tôt pour générer des pressions/relâchements de la souris et nous utilisons les actions du manche à balai pour générer des événements de la molette de la souris.

Enfin, nous ajoutons un retour haptique lorsque le site pickRay touche un objet :

XrHapticFeedback {
    controller: XrHapticFeedback.RightController
    condition: XrHapticFeedback.RisingEdge
    trigger: pickRay.hit
    hapticEffect: XrSimpleHapticEffect {
        amplitude: 0.5
        duration: 10
        frequency: 200
    }
}

L'effet haptique se déclenche chaque fois que la propriété pickRay.hit passe de false à true.

XrItem

La façon habituelle d'intégrer des interfaces utilisateur 2D dans des scènes 3D fonctionne également dans XR, mais comme l'unité de mesure est le centimètre, ces interfaces utilisateur devront être mises à l'échelle pour être utiles. Le type XrItem offre un moyen pratique d'effectuer la mise à l'échelle automatiquement en définissant la taille physique de l'élément 3D et la taille logique de la surface 2D.

XrItem {
    width: 75
    height: 100
    x: -100
    y: height + table.height + 5
    z: 40
    eulerRotation.y: 45
    color: "transparent"
    contentItem: Rectangle {
        color: Qt.rgba(1, 1, 1, 0.5)
        border.width: 5
        border.color: "lightblue"
        height: 400
        width: 300
        radius: 25
    ...
        }
    }

Nous positionnons le site XrItem en trois dimensions et lui donnons une largeur de 75 cm et une hauteur de 100 cm. Nous ajoutons ensuite un rectangle en tant qu'élément de contenu et lui attribuons une taille de 300 x 400 unités. Les autres éléments de l'interface utilisateur Qt Quick sont ajoutés en tant qu'enfants du rectangle de la manière habituelle et ne sont pas montrés ici. Le contenu 2D est automatiquement mis à l'échelle pour remplir le XrItem.

Exemple de projet @ code.qt.io

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.