Revision control
Copy as Markdown
// Copyright (C) 2025 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import QtQuick
import QtQuick3D
Model {
id: root
source: isSphere() ? "#Sphere" : "#Rectangle"
property real size: 1
property real contrast: 0.5
property Node cameraNode: null
property real scaleDistance: 100 // Cursor is scaled up when further away than this distance
property real sf: size / 100 // private property
opacity: 0.5
scale: Qt.vector3d(sf, sf, sf)
enum CursorStyle {
Hidden,
Flat,
Sphere
}
property int cursorStyle: XrCursor.CursorStyle.Flat
function isSphere() : bool {
return cursorStyle === XrCursor.CursorStyle.Sphere
}
CustomMaterial {
id: targetMaterial
shadingMode: CustomMaterial.Unshaded
cullMode: Material.BackFaceCulling
vertexShader: "shaders/cursor.vert"
fragmentShader: "shaders/cursor.frag"
property real opacity: root.cursorStyle === XrCursor.CursorStyle.Hidden ? 0.0 : root.opacity
property real contrast: root.contrast
}
PrincipledMaterial {
id: sphereMaterial
baseColor: "white"
}
materials: isSphere() ? sphereMaterial : targetMaterial
function setPositionAndOrientation(scenePos : vector3d, sceneNormal : vector3d) {
if (isSphere()) {
position = scenePos
} else {
const newPos = scenePos.minus(sceneNormal.normalized().times(-0.1))
rotation = Quaternion.lookAt(newPos, scenePos,
Qt.vector3d(0, 0, -1), Qt.vector3d(0, 1, 0))
position = newPos
}
if (cameraNode && scaleDistance) {
const distance = scenePos.minus(cameraNode.position).length()
const distanceScale = Math.max(1, distance / root.scaleDistance)
sf = size * distanceScale / 100
}
}
}