Qt Quick 3D - Exemple d'interaction 3D XR
Illustre comment manipuler des objets 3D à l'aide de l'Qt Quick e 3D XR.

Cet exemple montre comment créer des composants permettant de déplacer et de redimensionner des objets 3D dans une scène. Il utilise la même stratégie de sélection par rayons que l'exemple xr_input.
Entrée du contrôleur
Dans cet exemple, nous créons un composant réutilisable nommé AimController. Celui-ci effectue une sélection par rayons pour choisir un modèle et permet, en option, à l’utilisateur de saisir le modèle sélectionné et de le déplacer.
AimController Il définit des signaux qui nous permettent de mettre en œuvre des interactions personnalisées :
property Model hoveredObject: null
signal objectPressed(obj: Model, pos: vector3d, direction: vector3d)
signal moved(pos: vector3d, direction: vector3d)
signal released()
signal objectGrabbed(obj: Model)Gadgets
Nous définissons un composant abstrait, XrGadget, qui dispose de deux fonctions : handleControllerPress et handleControllerMove. En C++, ces fonctions auraient été virtuelles. Comme cet exemple est entièrement implémenté en QML, nous émettons à la place des signaux pouvant être gérés dans des sous-composants.
Par exemple, TranslateGadget déplace l’objet contrôlé le long de l’axe du gadget en fonction du signal onMoved:
onMoved: (pos, dir) => {
let moveDirection = delta.normalized()
let mapped_axis = controlledObject.mapDirectionToScene(axisDirection).normalized()
let dot = mapped_axis.dotProduct(moveDirection)
let offset = mapped_axis.times(delta.length() * dot)
controlledObject.position = originalPos.plus(offset)
}Rassembler le tout
Nous définissons un composant GadgetBox qui garde en mémoire l’objet sélectionné et affiche un cadre translucide autour de celui-ci, en plus d’afficher des gadgets autour de l’objet. Lorsqu’on appuie sur un objet sélectionné, le signal GadgetBox bascule entre les trois types de gadgets (translation, rotation et redimensionnement).
Dans ` main.qml `, nous réagissons aux signaux provenant de ` AimController ` et appelons les fonctions de ` GadgetBox` :
AimController {
id: rightAim
controller: XrController.RightController
view: xrView
enableVirtualMouse: true
enableThumbstickMove: thumbCheckBox.checked
onObjectPressed: (obj, pos, dir) => {
gadgetBox.handlePress(obj, pos, dir)
}
onHoveredObjectChanged: {
gadgetBox.handleHover(hoveredObject)
hapticFeedback.handleHover(hoveredObject)
}
onMoved: (pos, dir) => {
gadgetBox.handleMove(pos, dir)
}
onReleased: {
gadgetBox.handleRelease()
}
onObjectGrabbed: (obj) => {
if (!grabCheckBox.checked)
return
const gadget = obj as XrGadget
if (!gadget)
startGrab(obj)
else if (gadget.grabbable)
startGrab(gadget.controlledObject)
}
Model {
source: "#Cylinder"
scale: "0.05, 0.1, 0.05"
z: 5
eulerRotation.x: 90
materials: PrincipledMaterial {
baseColor: "black"
}
}
xrCursor: cursor
}Nous fournissons également un retour haptique lorsque l’objet ou le gadget survolé change :
XrHapticFeedback {
id: hapticFeedback
controller: XrHapticFeedback.RightController
hapticEffect: XrSimpleHapticEffect {
amplitude: 0.5
duration: 10
frequency: 200
}
property Model prevObj: null
function handleHover(obj: Model) {
if (obj && obj !== prevObj)
start()
prevObj = obj
}
}© 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.