1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
|
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import QtQuick
import QtQuick3D
import QtQuick3D.Helpers
import QtQuick3D.Xr
pragma ComponentBehavior: Bound
XrView {
id: xrView
referenceSpace: XrView.ReferenceSpaceStage
depthSubmissionEnabled: true
property list<color> colorTable: [Qt.rgba(1, 0, 1, 1), // magenta
Qt.rgba(0, 1, 0, 1), // green
Qt.rgba(0, 0.5, 0.5, 1), // darkCyan
Qt.rgba(0.5, 0.5, 0, 1), // darkYellow
Qt.rgba(0, 0, 1, 1), // blue
Qt.rgba(1, 0, 0, 1), // red
Qt.rgba(0.5, 0, 0, 1), // darkRed
Qt.rgba(1, 1, 0, 1)] // yellow
property list<color> extraColorTable: [Qt.rgba(0.5, 0.5, 0.5, 1), // dark gray
Qt.rgba(0.9, 0.9, 0.7, 1)] // beige
function colorForClassification(index) {
return colorTable[index > 0 && index < colorTable.length ? index : 0]
}
function colorForClassificationOther(classificationName) {
const index = ["screen", "storage"].indexOf(classificationName.toLowerCase())
return extraColorTable[index > 0 && index < extraColorTable.length ? index : 0]
}
function anchorColor(anchor) {
const classification = anchor.classification
if (classification === XrSpatialAnchor.Other)
return colorForClassificationOther(anchor.classificationString)
else
return colorForClassification(classification)
}
property bool preferPassthrough: true
passthroughEnabled: passthroughSupported && preferPassthrough
XrErrorDialog { id: err }
onInitializeFailed: (errorString) => {
console.log("===================>>>>>>" + errorString)
err.run("XRView", errorString)
}
environment: SceneEnvironment {
id: sceneEnvironment
lightProbe: Texture {
textureData: ProceduralSkyTextureData {
}
}
antialiasingMode: SceneEnvironment.MSAA
antialiasingQuality: SceneEnvironment.High
backgroundMode: xrView.passthroughEnabled ? SceneEnvironment.Transparent : SceneEnvironment.Color
clearColor: "skyblue"
probeHorizon: 0.5
}
xrOrigin: XrOrigin {
id: theOrigin
XrController {
id: rightController
controller: XrController.ControllerRight
poseSpace: XrController.AimPose
XrInputAction {
hand: XrInputAction.RightHand
actionId: [XrInputAction.Button2Pressed, XrInputAction.MiddleFingerPinch]
onTriggered: xrView.preferPassthrough = !xrView.preferPassthrough
}
onRotationChanged: {
const pickResult = xrView.rayPick(scenePosition, forward)
if (pickResult.hitType === PickResult.Model) {
pickRay.hit = true
pickRay.length = pickResult.distance
movableObject.move(pickResult.scenePosition, pickResult.sceneNormal)
movableObject.visible = true
const info = pickResult.objectHit?.anchorInfo
labelNode.anchorInfo = info ? info : "(unknown)"
} else {
pickRay.hit = false
pickRay.length = 50
labelNode.anchorInfo = "(no anchor)"
}
}
Node {
id: pickRay
property real length: 50
property bool hit: false
z: -length/2
Model {
eulerRotation.x: 90
scale: Qt.vector3d(0.02, pickRay.length/100, 0.02)
source: "#Cylinder"
materials: PrincipledMaterial { baseColor: pickRay.hit ? "green" : "gray" }
opacity: 0.5
}
}
}
}
Node {
id: movableObject
// This object is positioned on anchors where the ray hits
visible: false
function move(pos: vector3d, normal: vector3d) {
const rot = Quaternion.lookAt(pos, pos.plus(normal));
position = pos
rotation = rot
}
Model {
scale: Qt.vector3d(0.5, 0.05, 0.5)
eulerRotation.x: 90
z: -2.5
source: "#Cylinder"
materials: PrincipledMaterial {
baseColor: "red"
roughness: 0.5
}
}
}
//! [label]
Node {
id: labelNode
position: rightController.position
rotation: rightController.rotation
property int numAnchors: spatialAnchors.count
property string anchorInfo: "(no anchor)"
Node {
y: 15
x: -15
scale: Qt.vector3d(0.1, 0.1, 0.1)
Rectangle {
width: 300
height: 100
color: Qt.rgba(1,0.9,0.8,0.7)
radius: 10
border.width: 2
border.color: "blue"
Text {
anchors.fill: parent
anchors.margins: 10
textFormat: Text.StyledText
text: "Total anchors: " + labelNode.numAnchors + "<br>" + "Selected: " + labelNode.anchorInfo
}
}
}
}
//! [label]
//! [repeater]
Repeater3D {
id: spatialAnchors
model: XrSpatialAnchorListModel {
}
delegate: Node {
id: anchorNode
required property XrSpatialAnchor anchor
required property int index
position: anchor.position
rotation: anchor.rotation
Model {
pickable: true
z: anchorNode.anchor.has3DBounds ? anchorNode.anchor.offset3D.z / 2 * 100 : 0 // Position is center of 2D surface also for 3D anchors
scale: anchorNode.anchor.has3DBounds ? anchorNode.anchor.extent3D : Qt.vector3d(anchorNode.anchor.extent2D.x, anchorNode.anchor.extent2D.y, 0.01)
materials: PrincipledMaterial {
// Make anchor objects invisible in passthrough mode
baseColor: xrView.passthroughEnabled ? Qt.rgba(0, 0, 0, 0) : anchorColor(anchor)
alphaMode: xrView.passthroughEnabled ? PrincipledMaterial.Blend : PrincipledMaterial.Opaque
roughness: 0.7
}
source: anchorNode.anchor.has3DBounds ? "#Cube" : "#Rectangle"
property string anchorInfo: "anchor #" + anchorNode.index + ", " + anchorNode.anchor.classificationString
}
Model {
// Visualize anchor orientation
materials: PrincipledMaterial {
baseColor: anchorNode.anchor.has3DBounds ? anchorNode.anchor.has2DBounds ? "green" : "red" : "blue"
}
scale: Qt.vector3d(0.05, 0.05, 0.05)
source: "#Cube"
Model {
materials: PrincipledMaterial {
baseColor: "black"
}
scale: Qt.vector3d(0.1, 3, 0.1)
source: "#Cube"
y: 150
}
Model {
materials: PrincipledMaterial {
baseColor: "white"
}
scale: Qt.vector3d(3, 0.1, 0.1)
source: "#Cube"
x: 150
}
}
visible: anchor.has2DBounds || anchor.has3DBounds
}
}
//! [repeater]
}
|