Qt Quick 3D - XR 3D Interaction example
Demonstrates how to manipulate 3D objects with Qt Quick 3D XR.
This example shows how to create components that move and resize 3D objects in a scene. It uses the same ray-picking strategy as the xr_input example.
Controller input
In this example, we create a reusable component named AimController
. This performs ray picking to select a Model, and optionally allows the user to grab the selected Model and move it around.
AimController
defines signals that allows us to implement custom interactions:
signal objectPressed(obj: Model, pos: vector3d, direction: vector3d) signal objectHovered(obj: Model) signal moved(pos: vector3d, direction: vector3d) signal released()
Gadgets
We define an abstract component, XrGadget
, that has two functions: handleControllerPress
and handleControllerMove
. In C++, these functions would have been virtual. Since this example is implemented completely in QML, we instead emit signals that can be handled in sub-components.
For example, TranslateGadget
moves the controlled object along the gadget's axis based on the onMoved
signal:
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) }
Tying it all together
We define a component GadgetBox
that keeps track of which object is selected and shows a translucent box around the selected object, in addition to showing gadgets around the object. When a selected object is pressed, the GadgetBox
will cycle between the three different types of gadgets (translate, rotate, and resize).
In main.qml
we react to the signals from the AimController
and call the functions in GadgetBox
:
AimController { id: rightAim controller: XrController.ControllerRight onObjectPressed: (obj, pos, dir) => { gadgetBox.handlePress(obj, pos, dir) } onObjectHovered: (obj) => { gadgetBox.handleHover(obj) hapticFeedback.handleHover(obj) } onMoved: (pos, dir) => { gadgetBox.handleMove(pos, dir) } onReleased: { gadgetBox.handleRelease() } grabMoveEnabled: !gadgetBox.gadgetActive }
We also provide haptic feedback when the hovered object or gadget changes:
XrHapticFeedback { id: hapticFeedback controller: XrHapticFeedback.RightController hapticEffect: XrSimpleHapticEffect { amplitude: 0.5 duration: 30 frequency: 3000 } property Model prevObj: null function handleHover(obj: Model) { if (obj && obj !== prevObj) start() prevObj = obj } }
© 2024 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.