qtdoc/examples/demos/xr_physicsbase_teleportation/Main.qml

328 lines
9.3 KiB
QML
Raw Normal View History

// 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.Physics
import QtQuick3D.Physics.Helpers as Helpers
import QtQuick3D.Xr
import QtQuick3D.Particles3D
XrView {
id: xrView
XrErrorDialog { id: err }
onInitializeFailed: (errorString) => err.run("XR physics-base teleportation", errorString)
referenceSpace: XrView.ReferenceSpaceStage
environment: ExtendedSceneEnvironment {
id: extendedSceneEnvironment
backgroundMode: SceneEnvironment.Color
probeExposure: 0.7
lightProbe: Texture {
source: "media/textures/OpenfootageNET_lowerAustria01-1024.hdr"
}
skyboxBlurAmount: 0.0
specularAAEnabled: true
clearColor: theFog.color
exposure: teleporter.screenVisibility
fog: Fog {
id: theFog
color:"gray"
enabled: true
depthEnabled: true
depthNear: 1500
depthFar: 3000
}
}
Component.onCompleted: {
ParticleResources.init(xrView)
}
xrOrigin: XrOrigin {
id: xrOrigin
camera: XrCamera {
id: trackingCamera
Prompter {
id: prompter
}
}
XrController {
id: xrLeftController
controller: XrController.ControllerLeft
poseSpace: XrController.AimPose
TorchGripper {
hand: XrInputAction.LeftHand
}
}
XrController {
id: xrRightController
controller: XrController.ControllerRight
poseSpace: XrController.AimPose
XrInputAction {
id: thumbstickX
hand: XrInputAction.RightHand
actionId: [XrInputAction.ThumbstickX]
}
XrInputAction {
id: thumbstickY
hand: XrInputAction.RightHand
actionId: [XrInputAction.ThumbstickY]
}
XrInputAction {
id: trackpadX
hand: XrInputAction.RightHand
actionId: [XrInputAction.TrackpadX]
}
XrInputAction {
id: trackpadY
hand: XrInputAction.RightHand
actionId: [XrInputAction.TrackpadY]
}
XrInputAction {
id: trackpadPressed
hand: XrInputAction.RightHand
actionId: [XrInputAction.TrackpadPressed]
}
TorchGripper {
hand: XrInputAction.RightHand
}
property real xValue: trackpadPressed.pressed ? trackpadX.value : thumbstickX.value
property real yValue: trackpadPressed.pressed ? trackpadY.value : thumbstickY.value
}
}
PhysicsbaseTeleporter {
id: teleporter
rayPicker: xrView
cameraOrigin: xrOrigin
camera: xrOrigin.camera
beamHandle: xrRightController
characterController: character
xStickValue: xrRightController.xValue
yStickValue: xrRightController.yValue
onDoTeleportation: (cameraOriginPosition, characterControllerPosition)=> {
xrOrigin.position = cameraOriginPosition
character.teleport(characterControllerPosition)
}
onDoRotation: (cameraOriginRotation, cameraOriginPosition)=> {
xrOrigin.rotation = cameraOriginRotation
xrOrigin.position = cameraOriginPosition
}
}
PhysicsWorld {
id: physicsWorld
running: true
scene: xrView
gravity: Qt.vector3d(0, -981, 0)
}
CharacterController {
id: character
property bool inTheHouse: true
signal enteredTheHouse
signal leftTheHouse
onEnteredTheHouse: {
inTheHouse = true
}
onLeftTheHouse: {
inTheHouse = false
}
property vector3d startPos: Qt.vector3d(0, 200, 0)
scale: Qt.vector3d(0.5, 1.75, 0.5)
Component.onCompleted: {
prompter.prompt = Prompter.DarknessFalling
prompter.prompt = Prompter.PickupTorch
teleporter.teleportTo(character.startPos)
}
collisionShapes: CapsuleShape {
id: capsuleShape
}
onShapeHit: (body, position, impulse, normal)=>{
if (body.objectName === "Ground")
leftTheHouse()
else if (body.objectName === "HouseFloor")
enteredTheHouse()
}
enableShapeHitCallback: true
sendTriggerReports: true
gravity: physicsWorld.gravity.times(10) //make it fall faster
}
Ground {
}
Fence {
}
House {
}
Chair {
eulerRotation: Qt.vector3d(0, -45, 0)
position: Qt.vector3d(-200, 200, -300)
}
Table {
position: Qt.vector3d(-30, 200, -300)
}
Torch {
id: torch
position: Qt.vector3d(0, 350, -300)
eulerRotation: Qt.vector3d(-90, 0, 0)
windEnabled: !character.inTheHouse
onAttachedToChanged: {
if (attachedTo)
prompter.prompt = Prompter.LightupTorch
}
onIsOnChanged: {
prompter.prompt = Prompter.DefendCrop
}
}
Grass {
id: field
z: -1200
}
Stands {
}
Campfire {
id: campFire1
position: Qt.vector3d(1000, 185 ,1000)
function updateColors(){
if (campFire1.isOn && campFire2.isOn &&
campFire3.isOn && campFire4.isOn) {
campFire1.fireColor = "white"
campFire1.lightColor = Qt.lighter("orange", 1.5)
enemy.run = true
}else {
campFire1.fireColor = "orange"
campFire1.lightColor = "orange"
enemy.run = false
}
campFire2.fireColor = campFire1.fireColor
campFire2.lightColor = campFire1.lightColor
campFire3.fireColor = campFire1.fireColor
campFire3.lightColor = campFire1.lightColor
campFire4.fireColor = campFire1.fireColor
campFire4.lightColor = campFire1.lightColor
}
onIsOnChanged: {
campFire1.updateColors()
}
}
Campfire {
id: campFire2
position: Qt.vector3d(1000, 185 ,-1000)
onIsOnChanged: {
campFire1.updateColors()
}
}
Campfire {
id: campFire3
position: Qt.vector3d(-1000, 185 ,1000)
onIsOnChanged: {
campFire1.updateColors()
}
}
Campfire {
id: campFire4
position: Qt.vector3d(-1000, 185 ,-1000)
onIsOnChanged: {
campFire1.updateColors()
}
}
Smoke {
id: enemy
readonly property real maxY: 5000
readonly property real startY: 40000
property bool run: false
position: Qt.vector3d(0, startY, 0)
color: "black"
colorVariation: 0.0
size: run ? 6.0 : 4.0
FrameAnimation {
running: true
property real time: 0
property real fieldEncounterTime: 0
onTriggered: {
time += 0.5 * frameTime
let enemyLinearY = enemy.scenePosition.y / enemy.maxY
let enemyOffset = enemyLinearY * 5000 + 200
let targetBase = field.scenePosition
let enemyMovementSpeed = 20.
let chaseTheCamera = false
if (fieldEncounterTime > 0.99 && !character.inTheHouse && !enemy.run) {
targetBase = xrOrigin.camera.scenePosition
enemyOffset = 20
chaseTheCamera = true
enemyMovementSpeed = 5
}
let target = Qt.vector3d(targetBase.x + Math.cos(time) * enemyOffset ,
targetBase.y + Math.abs(Math.cos(time)) * 100,
targetBase.z + Math.sin(time) * enemyOffset)
if (torch.isOn) {
let enemyToTorchDir =  torch.scenePosition.minus(enemy.position)
let enemyToTorchLen = enemyToTorchDir.length()
let dis = Math.max(0, 500 - enemyToTorchLen)
target.y += dis * dis * dis
}
if (enemy.run)
target.y += enemy.maxY
if (!chaseTheCamera) {
field.baseColor = ""
if (field.scenePosition.minus(enemy.scenePosition).length() < 500)
fieldEncounterTime += frameTime * 0.02
else
fieldEncounterTime -= frameTime * 0.01
fieldEncounterTime = Math.min(Math.max(fieldEncounterTime, 0), 1.)
field.baseColor = Qt.darker("white", Math.exp(fieldEncounterTime))
}
let enemyToTargetDir = target.minus(enemy.scenePosition).normalized().times(enemyMovementSpeed)
enemy.position = enemy.scenePosition.plus(enemyToTargetDir)
}
}
}
}